diff options
author | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-10-05 12:48:05 +1000 |
---|---|---|
committer | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-10-05 12:48:05 +1000 |
commit | dfb6adbcbcc7d50b770b6d5ea82efdd8f8c32e25 (patch) | |
tree | a470b91a90716d7ea46fde53ed395449c24583a2 /src | |
parent | 54354e32c6498cc7f8839ab4deb1208d37216cc5 (diff) |
delete documentation workflow
Diffstat (limited to 'src')
96 files changed, 0 insertions, 10848 deletions
diff --git a/src/animation.c b/src/animation.c deleted file mode 100644 index d7973dc..0000000 --- a/src/animation.c +++ /dev/null @@ -1,90 +0,0 @@ -#include "animation.h" -#include "immdraw.h" -#include "log.h" -#include "maths.h" -#include "maths_types.h" -#include "ral_types.h" - -Keyframe Animation_Sample(AnimationSampler* sampler, f32 t) { - size_t previous_index = 0; - f32 previous_time = 0.0; - // look forwards - DEBUG("%d\n", keyframe_kind_strings[sampler->animation.values.kind]); - TRACE("Total timestamps %d", sampler->animation.n_timestamps); - for (u32 i = 0; i < sampler->animation.n_timestamps; i++) { - f32 current_time = sampler->animation.timestamps[i]; - if (current_time > t) { - break; - } - previous_time = sampler->animation.timestamps[i]; - previous_index = i; - } - - size_t next_index = (previous_index + 1) % sampler->animation.n_timestamps; - f32 next_time = sampler->animation.timestamps[next_index]; - printf("%d %f %d %f\n", previous_index, previous_time, next_index, next_time); - - Keyframe prev_value = sampler->animation.values.values[previous_index]; - Keyframe next_value = sampler->animation.values.values[next_index]; - - printf("%d %d\n", previous_index, next_index); - - f32 time_diff = - sampler->animation.timestamps[next_index] - sampler->animation.timestamps[previous_index]; - f32 percent = (t - previous_time) / time_diff; - - switch (sampler->animation.values.kind) { - case KEYFRAME_ROTATION: - return (Keyframe){ .rotation = quat_slerp( - sampler->animation.values.values[previous_index].rotation, - sampler->animation.values.values[next_index].rotation, percent) }; - case KEYFRAME_TRANSLATION: - case KEYFRAME_SCALE: - case KEYFRAME_WEIGHTS: - WARN("TODO: other keyframe kind interpolation"); - return prev_value; - } -} - -void Animation_Tick(AnimationClip* clip, Armature* armature, f32 time) { - TRACE("Ticking animation %s", clip->clip_name); - - for (u32 c_i = 0; c_i < clip->channels->len; c_i++) { - AnimationSampler* sampler = clip->channels->data; - - // Interpolated keyframe based on time - Keyframe k = Animation_Sample(sampler, time); - - // Get the joint in the armature - Joint* joint = &armature->joints->data[sampler->target_joint_idx]; - if (sampler->animation.values.kind == KEYFRAME_ROTATION) { - // Update the joints rotation - joint->transform_components.rotation = k.rotation; - } else { - WARN("not yet implemented animation kind"); - } - } -} - -void Animation_VisualiseJoints(Armature* armature) { - for (int j = 0; j < armature->joints->len; j++) { - Joint joint = armature->joints->data[j]; - Transform tf = joint.transform_components; - tf.scale = vec3(0.05, 0.05, 0.05); - Immdraw_Sphere(tf, vec4(0, 1, 1, 1), true); - } -} - -ShaderDataLayout AnimData_GetLayout(void* data) { - AnimDataUniform* d = data; - bool has_data = data != NULL; - - ShaderBinding b1 = { .label = "AnimData", - .kind = BINDING_BYTES, - .data.bytes.size = sizeof(AnimDataUniform) }; - - if (has_data) { - b1.data.bytes.data = d; - } - return (ShaderDataLayout){ .bindings = { b1 }, .binding_count = 1 }; -} diff --git a/src/animation.h b/src/animation.h deleted file mode 100644 index 5883f13..0000000 --- a/src/animation.h +++ /dev/null @@ -1,122 +0,0 @@ -#pragma once - -#include "cgltf.h" -#include "darray.h" -#include "defines.h" -#include "maths_types.h" -#include "ral_types.h" - -typedef enum Interpolation { - INTERPOLATION_STEP, - INTERPOLATION_LINEAR, - INTERPOLATION_CUBIC, /** @brief Cubic spline interpolation */ - INTERPOLATION_COUNT -} Interpolation; - -typedef enum KeyframeKind { - KEYFRAME_ROTATION, - KEYFRAME_TRANSLATION, - KEYFRAME_SCALE, - KEYFRAME_WEIGHTS, -} KeyframeKind; - -static const char* keyframe_kind_strings[4] = { "ROTATION", "TRANSLATION", "SCALE", "WEIGHTS"}; - -typedef union Keyframe { - Quat rotation; - Vec3 translation; - Vec3 scale; - f32 weights[4]; -} Keyframe; - -typedef struct Keyframes { - KeyframeKind kind; - Keyframe* values; - size_t count; -} Keyframes; - -typedef struct Joint { - // used instead of pointers later to update correct joints - size_t node_idx; - ssize_t parent; // parent bone. -1 means its the root - size_t children[8]; // children bones, upto 8 - u8 children_count; - char* debug_label; // optional - Mat4 inverse_bind_matrix; - Mat4 local_transform; - /** @brief holds position, rotation, and scale that will be written to by animation - samplers every tick of the animation system. */ - Transform transform_components; -} Joint; -#ifndef TYPED_JOINT_ARRAY -KITC_DECL_TYPED_ARRAY(Joint); -#define TYPED_JOINT_ARRAY -#endif - -typedef u32 JointIdx; - -typedef struct Armature { - char* label; - Joint_darray* joints; -} Armature; - -// NOTE: I think we will need to topologically sort the joints to store them in array if we want to -// do linear array traversal -// when calculating transforms. - -typedef struct AnimationSpline { - f32* timestamps; - size_t n_timestamps; - Keyframes values; - Interpolation interpolation; -} AnimationSpline; - -// combines a sampler and a channel in gltf -typedef struct AnimationSampler { - int current_index; - f32 min; - f32 max; - AnimationSpline animation; - u32 target_joint_idx; // index into the array of joints in an armature -} AnimationSampler; -#ifndef TYPED_ANIM_SAMPLER_ARRAY -KITC_DECL_TYPED_ARRAY(AnimationSampler); -#define TYPED_ANIM_SAMPLER_ARRAY -#endif - -/** @brief Sample an animation at a given time `t` returning an interpolated keyframe */ -PUB Keyframe Animation_Sample(AnimationSampler* sampler, f32 t); - -/** @brief A clip contains one or more animation curves. */ -typedef struct AnimationClip { - const char* clip_name; - bool is_playing; - f32 time; - AnimationSampler_darray* channels; -} AnimationClip; -#ifndef TYPED_ANIM_CLIP_ARRAY -KITC_DECL_TYPED_ARRAY(AnimationClip); -#define TYPED_ANIM_CLIP_ARRAY -#endif - -// typedef struct SkinnedAnimation { -// Mat4* joint_matrices; -// size_t n_joints; -// } SkinnedAnimation; - -PUB void Animation_Play(AnimationClip* clip); - -void Animation_Tick(AnimationClip* clip, Armature* armature, f32 delta_time); - -void Animation_VisualiseJoints(Armature* armature); - -#define MAX_BONES 100 - -typedef struct AnimDataUniform { - Mat4 bone_matrices[MAX_BONES]; -} AnimDataUniform; -ShaderDataLayout AnimData_GetLayout(void* data); - -// Animation Targets: -// - Mesh -// - Joint diff --git a/src/collision.c b/src/collision.c deleted file mode 100644 index 81cbcfc..0000000 --- a/src/collision.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "immdraw.h" -#include "maths.h" -#include "maths_types.h" -#include "physics.h" - -PUB void Debug_DrawOBB(OBB obb) { - Transform t = transform_create(obb.center, obb.rotation, vec3_sub(obb.bbox.max, obb.bbox.min)); - Immdraw_Cuboid(t, vec4(0.0, 0.8, 0.1, 1.0), true); -} diff --git a/src/colours.h b/src/colours.h deleted file mode 100644 index ac8996a..0000000 --- a/src/colours.h +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once - -#include "defines.h" - -typedef struct rgba { - f32 r, g, b, a; -} rgba; - -#define COLOUR_BLACK ((rgba){ 0.02, 0.02, 0.0, 1.0 }) -#define COLOUR_IMPERIAL_RED ((rgba){ 0.97, 0.09, 0.21, 1.0 }) -#define COLOUR_TRUE_BLUE ((rgba){ 0.11, 0.41, 0.77, 1.0 }) -#define COLOUR_SEA_GREEN ((rgba){ 0.18, 0.77, 0.71, 1.0 }) -#define COLOUR_WHITE ((rgba){ 1.0, 1.0, 1.0, 1.0 }) - -#define rgba_to_vec4(color) (vec4(color.r, color.g, color.b, color.a)) -#define rgba_to_vec3(color) (vec3(color.r, color.g, color.b)) - -// Thanks ChatGPT -#define STONE_50 ((rgba){ 0.980, 0.980, 0.976, 1.0 }) -#define STONE_100 ((rgba){ 0.961, 0.961, 0.957, 1.0 }) -#define STONE_200 ((rgba){ 0.906, 0.898, 0.894, 1.0 }) -#define STONE_300 ((rgba){ 0.839, 0.827, 0.819, 1.0 }) -#define STONE_400 ((rgba){ 0.659, 0.635, 0.620, 1.0 }) -#define STONE_500 ((rgba){ 0.471, 0.443, 0.424, 1.0 }) -#define STONE_600 ((rgba){ 0.341, 0.325, 0.306, 1.0 }) -#define STONE_700 ((rgba){ 0.267, 0.251, 0.235, 1.0 }) -#define STONE_800 ((rgba){ 0.161, 0.145, 0.141, 1.0 }) -#define STONE_900 ((rgba){ 0.110, 0.098, 0.090, 1.0 }) -#define STONE_950 ((rgba){ 0.047, 0.043, 0.035, 1.0 }) - -#define CYAN_50 ((rgba){ 0.930, 1.000, 1.000, 1.0 }) -#define CYAN_100 ((rgba){ 0.810, 0.980, 1.000, 1.0 }) -#define CYAN_200 ((rgba){ 0.650, 0.953, 0.988, 1.0 }) -#define CYAN_300 ((rgba){ 0.404, 0.910, 0.976, 1.0 }) -#define CYAN_400 ((rgba){ 0.133, 0.827, 0.933, 1.0 }) -#define CYAN_500 ((rgba){ 0.023, 0.714, 0.831, 1.0 }) -#define CYAN_600 ((rgba){ 0.031, 0.569, 0.698, 1.0 }) -#define CYAN_700 ((rgba){ 0.055, 0.455, 0.565, 1.0 }) -#define CYAN_800 ((rgba){ 0.082, 0.369, 0.459, 1.0 }) -#define CYAN_900 ((rgba){ 0.086, 0.306, 0.388, 1.0 }) -#define CYAN_950 ((rgba){ 0.033, 0.200, 0.263, 1.0 }) - -#define GRAY_50 ((rgba){ 0.976, 0.980, 0.984, 1.0 }) -#define GRAY_100 ((rgba){ 0.953, 0.957, 0.965, 1.0 }) -#define GRAY_200 ((rgba){ 0.898, 0.906, 0.922, 1.0 }) -#define GRAY_300 ((rgba){ 0.820, 0.835, 0.859, 1.0 }) -#define GRAY_400 ((rgba){ 0.612, 0.639, 0.686, 1.0 }) -#define GRAY_500 ((rgba){ 0.420, 0.447, 0.502, 1.0 }) -#define GRAY_600 ((rgba){ 0.294, 0.333, 0.388, 1.0 }) -#define GRAY_700 ((rgba){ 0.216, 0.255, 0.318, 1.0 }) -#define GRAY_800 ((rgba){ 0.122, 0.161, 0.216, 1.0 }) -#define GRAY_900 ((rgba){ 0.067, 0.094, 0.153, 1.0 }) -#define GRAY_950 ((rgba){ 0.012, 0.027, 0.071, 1.0 }) - -#define RED_50 ((rgba){ 0.996, 0.949, 0.949, 1.0 }) -#define RED_100 ((rgba){ 0.996, 0.886, 0.886, 1.0 }) -#define RED_200 ((rgba){ 0.996, 0.792, 0.792, 1.0 }) -#define RED_300 ((rgba){ 0.988, 0.647, 0.647, 1.0 }) -#define RED_400 ((rgba){ 0.973, 0.443, 0.443, 1.0 }) -#define RED_500 ((rgba){ 0.937, 0.267, 0.267, 1.0 }) -#define RED_600 ((rgba){ 0.863, 0.149, 0.149, 1.0 }) -#define RED_700 ((rgba){ 0.725, 0.110, 0.110, 1.0 }) -#define RED_800 ((rgba){ 0.600, 0.106, 0.106, 1.0 }) -#define RED_900 ((rgba){ 0.498, 0.114, 0.114, 1.0 }) -#define RED_950 ((rgba){ 0.271, 0.039, 0.039, 1.0 }) - -#define ORANGE_50 ((rgba){ 1.000, 0.969, 0.929, 1.0 }) -#define ORANGE_100 ((rgba){ 1.000, 0.929, 0.835, 1.0 }) -#define ORANGE_200 ((rgba){ 0.996, 0.843, 0.667, 1.0 }) -#define ORANGE_300 ((rgba){ 0.992, 0.729, 0.455, 1.0 }) -#define ORANGE_400 ((rgba){ 0.984, 0.573, 0.235, 1.0 }) -#define ORANGE_500 ((rgba){ 0.976, 0.451, 0.086, 1.0 }) -#define ORANGE_600 ((rgba){ 0.918, 0.345, 0.047, 1.0 }) -#define ORANGE_700 ((rgba){ 0.761, 0.255, 0.047, 1.0 }) -#define ORANGE_800 ((rgba){ 0.604, 0.204, 0.071, 1.0 }) -#define ORANGE_900 ((rgba){ 0.486, 0.176, 0.071, 1.0 }) -#define ORANGE_950 ((rgba){ 0.263, 0.078, 0.027, 1.0 }) - -#define AMBER_50 ((rgba){ 1.000, 0.984, 0.922, 1.0 }) -#define AMBER_100 ((rgba){ 0.996, 0.953, 0.780, 1.0 }) -#define AMBER_200 ((rgba){ 0.992, 0.902, 0.541, 1.0 }) -#define AMBER_300 ((rgba){ 0.988, 0.827, 0.302, 1.0 }) -#define AMBER_400 ((rgba){ 0.984, 0.749, 0.141, 1.0 }) -#define AMBER_500 ((rgba){ 0.961, 0.620, 0.043, 1.0 }) -#define AMBER_600 ((rgba){ 0.851, 0.467, 0.024, 1.0 }) -#define AMBER_700 ((rgba){ 0.706, 0.325, 0.035, 1.0 }) -#define AMBER_800 ((rgba){ 0.573, 0.251, 0.055, 1.0 }) -#define AMBER_900 ((rgba){ 0.471, 0.208, 0.059, 1.0 }) -#define AMBER_950 ((rgba){ 0.271, 0.102, 0.012, 1.0 }) diff --git a/src/core/README.md b/src/core/README.md deleted file mode 100644 index 19cc1d0..0000000 --- a/src/core/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Core - -Core engine facilities diff --git a/src/core/animation.c b/src/core/animation.c deleted file mode 100644 index e69de29..0000000 --- a/src/core/animation.c +++ /dev/null diff --git a/src/core/camera.c b/src/core/camera.c deleted file mode 100644 index 77ddad6..0000000 --- a/src/core/camera.c +++ /dev/null @@ -1,90 +0,0 @@ -#include "camera.h" - -#include "input.h" -#include "keys.h" -#include "maths.h" - -#define CAMERA_SPEED 0.2 -#define CAMERA_SENSITIVITY 0.5 - -Camera Camera_Create(Vec3 pos, Vec3 front, Vec3 up, f32 fov) { - Camera c = { .position = pos, .front = front, .up = up, .fov = fov }; - return c; -} - -Mat4 Camera_ViewProj(Camera* c, f32 lens_height, f32 lens_width, Mat4* out_view, Mat4* out_proj) { - Mat4 proj = mat4_perspective(c->fov, lens_width / lens_height, 0.1, 1000.0); - Vec3 camera_direction = vec3_add(c->position, c->front); - Mat4 view = mat4_look_at(c->position, camera_direction, c->up); - if (out_view) { - *out_view = view; - } - if (out_proj) { - *out_proj = proj; - } - return mat4_mult(view, proj); -} - -void FlyCamera_Update(Camera* camera) { - static f32 yaw = 0.0; - static f32 pitch = 0.0; - - // Keyboard - f32 speed = CAMERA_SPEED; - Vec3 horizontal = vec3_cross(camera->front, camera->up); - if (key_is_pressed(KEYCODE_A) || key_is_pressed(KEYCODE_KEY_LEFT)) { - Vec3 displacement = vec3_mult(horizontal, -speed); - camera->position = vec3_add(camera->position, displacement); - } - if (key_is_pressed(KEYCODE_D) || key_is_pressed(KEYCODE_KEY_RIGHT)) { - Vec3 displacement = vec3_mult(horizontal, speed); - camera->position = vec3_add(camera->position, displacement); - } - if (key_is_pressed(KEYCODE_W) || key_is_pressed(KEYCODE_KEY_UP)) { - Vec3 displacement = vec3_mult(camera->front, speed); - camera->position = vec3_add(camera->position, displacement); - } - if (key_is_pressed(KEYCODE_S) || key_is_pressed(KEYCODE_KEY_DOWN)) { - Vec3 displacement = vec3_mult(camera->front, -speed); - camera->position = vec3_add(camera->position, displacement); - } - if (key_is_pressed(KEYCODE_Q)) { - Vec3 displacement = vec3_mult(camera->up, speed); - camera->position = vec3_add(camera->position, displacement); - } - if (key_is_pressed(KEYCODE_E)) { - Vec3 displacement = vec3_mult(camera->up, -speed); - camera->position = vec3_add(camera->position, displacement); - } - - // Mouse - if (MouseBtn_Held(MOUSEBTN_LEFT)) { - mouse_state mouse = Input_GetMouseState(); - // printf("Delta x: %d Delta y %d\n",mouse.x_delta, mouse.y_delta ); - - f32 x_offset = mouse.x_delta; - f32 y_offset = -mouse.y_delta; - - f32 sensitivity = CAMERA_SENSITIVITY; // change this value to your liking - x_offset *= sensitivity; - y_offset *= sensitivity; - - yaw += x_offset; - pitch += y_offset; - - // make sure that when pitch is out of bounds, screen doesn't get flipped - if (pitch > 89.0f) pitch = 89.0f; - if (pitch < -89.0f) pitch = -89.0f; - - Vec3 front; - front.x = cos(deg_to_rad(yaw) * cos(deg_to_rad(pitch))); - front.y = sin(deg_to_rad(pitch)); - front.z = sin(deg_to_rad(yaw)) * cos(deg_to_rad(pitch)); - front = vec3_normalise(front); - camera->front.x = front.x; - camera->front.y = front.y; - camera->front.z = front.z; - } - - // TODO: Right mouse => pan in screen space -} diff --git a/src/core/camera.h b/src/core/camera.h deleted file mode 100644 index 4300f87..0000000 --- a/src/core/camera.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "defines.h" -#include "maths_types.h" - -// TODO: swap to position + quaternion - -typedef struct Camera { - Vec3 position; - Vec3 front; - Vec3 up; - f32 fov; -} Camera; - -/** @brief create a camera */ -PUB Camera Camera_Create(Vec3 pos, Vec3 front, Vec3 up, f32 fov); - -/** - * @brief Get 3D camera transform matrix - * @param out_view optionally stores just the view matrix - * @param out_proj optionally stores just the projection matrix - * @returns the camera's view projection matrix pre-multiplied - */ -PUB Mat4 Camera_ViewProj(Camera* c, f32 lens_height, f32 lens_width, Mat4* out_view, - Mat4* out_proj); - -/** @brief Get 2D camera transform matrix */ -PUB Mat4 Camera_View2D(Camera* c); // TODO: 2D cameras - -struct Input_State; - -PUB void FlyCamera_Update(Camera* camera); - -// TODO: (HIGH) Basic reusable camera controls -/* -Right click + move = pan -Left click = orbit camera -WASD = forward/backward/left/right -*/ diff --git a/src/core/core.c b/src/core/core.c deleted file mode 100644 index 64f59f3..0000000 --- a/src/core/core.c +++ /dev/null @@ -1,81 +0,0 @@ -#include "core.h" - -#include <stdlib.h> - -#include "glfw3.h" -#include "input.h" -#include "keys.h" -#include "log.h" -#include "mem.h" -#include "render.h" -#include "render_types.h" - -// These are only the initial window dimensions -#define SCR_WIDTH 1000 -#define SCR_HEIGHT 1000 - -Core g_core; /** @brief global `Core` that other files can use */ - -/** @brief Gets the global `Core` singleton */ -inline Core* GetCore() { return &g_core; } - -void Core_Bringup(const char* window_name, struct GLFWwindow* optional_window) { - INFO("Initiate Core bringup"); - memset(&g_core, 0, sizeof(Core)); - - RendererConfig conf = { .window_name = window_name, - .scr_width = SCR_WIDTH, - .scr_height = SCR_HEIGHT, - .clear_colour = (Vec3){ .08, .08, .1 } }; - - g_core.renderer = malloc(Renderer_GetMemReqs()); - - // Initialise all subsystems - - // renderer config, renderer ptr, ptr to store a window, and optional preexisting glfw window - if (!Renderer_Init(conf, g_core.renderer, &g_core.window, optional_window)) { - // FATAL("Failed to start renderer"); - ERROR_EXIT("Failed to start renderer\n"); - } - if (optional_window != NULL) { - g_core.window = optional_window; - } - - if (!Input_Init(&g_core.input, g_core.window)) { - // the input system needs the glfw window which is created by the renderer - // hence the order here is important - ERROR_EXIT("Failed to start input system\n"); - } - - size_t model_data_max = 1024 * 1024 * 1024; - arena model_arena = arena_create(malloc(model_data_max), model_data_max); - - Model_pool model_pool = Model_pool_create(&model_arena, 256, sizeof(Model)); - g_core.models = model_pool; - INFO("Created model pool allocator"); -} - -void Core_Shutdown() { - Input_Shutdown(&g_core.input); - Renderer_Shutdown(g_core.renderer); - free(g_core.renderer); -} - -bool ShouldExit() { - return key_just_released(KEYCODE_ESCAPE) || glfwWindowShouldClose(g_core.window); -} - -void Frame_Begin() { - Input_Update(&g_core.input); - Render_FrameBegin(g_core.renderer); -} -void Frame_Draw() {} -void Frame_End() { Render_FrameEnd(g_core.renderer); } - -Core* get_global_core() { return &g_core; } - -GLFWwindow* Core_GetGlfwWindowPtr(Core* core) { return g_core.window; } - -struct Renderer* Core_GetRenderer(Core* core) { return core->renderer; } - -Model* Model_Get(ModelHandle h) { return Model_pool_get(&g_core.models, h); } diff --git a/src/core/core.h b/src/core/core.h deleted file mode 100644 index 14ba65d..0000000 --- a/src/core/core.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include "input.h" -#include "mem.h" -#include "render_types.h" -#include "screenspace.h" -#include "terrain.h" -#include "text.h" - -TYPED_POOL(Model, Model) -#define MODEL_GET(h) (Model_pool_get(&g_core.models, h)) -Model* Model_Get(ModelHandle h); - -typedef struct GLFWwindow GLFWwindow; - -typedef struct Core { - const char* app_name; - GLFWwindow* window; - Renderer* renderer; - Input_State input; - // Model_pool models; -} Core; -extern Core g_core; - -struct Renderer; - -Core* get_global_core(); - -/** - @brief Throws error if the core cannot be instantiated - @param [in] optional_window - Leave NULL if you want Celeritas to instantiate its own window with - GLFW, if you want to provide the glfw window then pass it in here. -*/ -void Core_Bringup(const char* window_name, GLFWwindow* optional_window); -void Core_Shutdown(); -bool ShouldExit(); - -GLFWwindow* Core_GetGlfwWindowPtr(Core* core); -struct Renderer* Core_GetRenderer(Core* core); - -void Frame_Begin(); -void Frame_Draw(); -void Frame_End(); diff --git a/src/core/input.c b/src/core/input.c deleted file mode 100644 index e69de29..0000000 --- a/src/core/input.c +++ /dev/null diff --git a/src/core/triggers.h b/src/core/triggers.h deleted file mode 100644 index a823890..0000000 --- a/src/core/triggers.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "defines.h" - -// Events/signals that get triggered by certain things that happen - -/* -e.g. -collider enters volume (collider) -collider exits volume (collider) - -you could create a custom signal that only triggers when a collider has been inside a volume for 3 -seconds listen for Enter, start timer, if hits 3 -> emit signal. Else, reset state - -Top-level triggers: -level loaded - -*/
\ No newline at end of file diff --git a/src/core/vfs.h b/src/core/vfs.h deleted file mode 100644 index 41033f5..0000000 --- a/src/core/vfs.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once -#include "defines.h" - -#define MAX_VIRTUAL_FILENAME_LEN 256 - -typedef struct VFS_Pack VFS_Pack; - -const char VFS_OpenErr_DoesNotExist[] = "PATH DOES NOT EXIST"; - -typedef struct VFS_File { - size_t n_bytes; - void* data; -} VFS_File; - -// virtual file open result -typedef struct VFS_FileRes { - bool success; - const char* error_reason; - VFS_File file; -} VFS_FileRes; - -VFS_Pack* VFS_Open(const char* filepath); - -bool VFS_Close(VFS_Pack*); - -VFS_FileRes VFS_VirtualRead(VFS_Pack* vfs, const char* unique_path); - -typedef struct VFS_PackBuilder { - const char* pack_filename; -} VFS_PackBuilder; - -typedef struct VFS_FileEntry { - char filename[MAX_VIRTUAL_FILENAME_LEN]; - size_t offset; - size_t size; -} VFS_FileEntry; - -VFS_PackBuilder VFS_Pack_Create();
\ No newline at end of file diff --git a/src/empty.c b/src/empty.c deleted file mode 100644 index b40cc85..0000000 --- a/src/empty.c +++ /dev/null @@ -1,3 +0,0 @@ -// For some reason on Mac we need an empty file so that 'ar' has something -// to run. -int add(int a, int b) { return a + b; }
\ No newline at end of file diff --git a/src/log.c b/src/log.c deleted file mode 100644 index 8bb7a65..0000000 --- a/src/log.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "log.h" - -#include <stdarg.h> -#include <stdio.h> -#include <string.h> - -#include "defines.h" - -// Regular text -#define BLK "\e[0;30m" -#define RED "\e[0;31m" -#define GRN "\e[0;32m" -#define YEL "\e[0;33m" -#define BLU "\e[0;34m" -#define MAG "\e[0;35m" -#define CYN "\e[0;36m" -#define WHT "\e[0;37m" -#define CRESET "\e[0m" - -static const char* level_strings[6] = { "[FATAL]: ", "[ERROR]: ", "[WARN]: ", - "[INFO]: ", "[DEBUG]: ", "[TRACE]: " }; -static const char* level_colours[6] = { RED, RED, YEL, BLU, CYN, MAG }; - -bool logger_init() { - // TODO: create log file - return true; -} - -void logger_shutdown() { - // does nothing right now -} - -void log_output(log_level level, const char* message, ...) { - char out_message[32000]; - memset(out_message, 0, sizeof(out_message)); - - // format original message - __builtin_va_list arg_ptr; - va_start(arg_ptr, message); - vsnprintf(out_message, 32000, message, arg_ptr); - va_end(arg_ptr); - - char out_message2[32006]; - // prepend log level string - sprintf(out_message2, "%s%s%s%s\n", level_colours[level], level_strings[level], out_message, - CRESET); - - // print message to console - printf("%s", out_message2); -} - -void report_assertion_failure(const char* expression, const char* message, const char* file, - int line) { - log_output(LOG_LEVEL_FATAL, "Assertion failure: %s, message: '%s', in file: %s, on line %d\n", - expression, message, file, line); -} diff --git a/src/log.h b/src/log.h deleted file mode 100644 index 537cb6e..0000000 --- a/src/log.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> - -#define ERROR_EXIT(...) \ - { \ - fprintf(stderr, __VA_ARGS__); \ - exit(1); \ - } - -#define TODO(msg) \ - do { \ - ERROR_EXIT("TODO: %s", msg); \ - } while (0) - -#define LOG_WARN_ENABLED 1 -#define LOG_INFO_ENABLED 1 - -#ifdef CRELEASE -#define LOG_DEBUG_ENABLED 0 -#define LOG_TRACE_ENABLED 0 -#else -#define LOG_DEBUG_ENABLED 1 -#define LOG_TRACE_ENABLED 1 -#endif - -typedef enum log_level { - LOG_LEVEL_FATAL = 0, - LOG_LEVEL_ERROR = 1, - LOG_LEVEL_WARN = 2, - LOG_LEVEL_INFO = 3, - LOG_LEVEL_DEBUG = 4, - LOG_LEVEL_TRACE = 5, -} log_level; - -bool logger_init(); -void logger_shutdown(); - -// TODO: macro that outputs logger macros for a specific subsystem or string prefix e.g. "MEMORY" -> -// logs now have more context potentially have line numbers too? - -void log_output(log_level level, const char* message, ...); - -#define FATAL(message, ...) log_output(LOG_LEVEL_FATAL, message, ##__VA_ARGS__) -#define ERROR(message, ...) log_output(LOG_LEVEL_ERROR, message, ##__VA_ARGS__) -#define WARN(message, ...) log_output(LOG_LEVEL_WARN, message, ##__VA_ARGS__) -#define INFO(message, ...) log_output(LOG_LEVEL_INFO, message, ##__VA_ARGS__) - -#if LOG_DEBUG_ENABLED == 1 -#define DEBUG(message, ...) log_output(LOG_LEVEL_DEBUG, message, ##__VA_ARGS__) -#else -#define DEBUG(message, ...) -#endif - -#if LOG_TRACE_ENABLED == 1 -#define TRACE(message, ...) log_output(LOG_LEVEL_TRACE, message, ##__VA_ARGS__) -#else -#define TRACE(message, ...) -#endif - -// TODO: Move this to an asserts file - -void report_assertion_failure(const char* expression, const char* message, const char* file, - int line); - -#define CASSERT(expr) \ - { \ - if (expr) { \ - } else { \ - report_assertion_failure(#expr, "", __FILE__, __LINE__); \ - __builtin_trap(); \ - } \ - } - -#define CASSERT_MSG(expr, msg) \ - { \ - if (expr) { \ - } else { \ - report_assertion_failure(#expr, msg, __FILE__, __LINE__); \ - __builtin_trap(); \ - } \ - }
\ No newline at end of file diff --git a/src/logos/README.md b/src/logos/README.md deleted file mode 100644 index 25b7bef..0000000 --- a/src/logos/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Logos - -Logos is the namespace for threadpool & job system code. This is not a 'system' as it is underlying core unit of the engine. - -Threadpool currently gets initialised at core bringup with a set number of threads and results are processed once per frame -on the main thread. This is subject to change but multithreading is not the highest priority right now.
\ No newline at end of file diff --git a/src/logos/tasks.h b/src/logos/tasks.h deleted file mode 100644 index 2e3dc53..0000000 --- a/src/logos/tasks.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Common jobs that get run - */ -#pragma once -#include "defines.h" -#include "logos/threadpool.h" -#include "render_types.h" -#include "str.h" - -typedef enum TaskLifetime { - /** ephemeral tasks must be finished by the end of the frame and thus we use a leak and clear - allocation strategy */ - TASK_EPHEMERAL, - /** multi-frame tasks have a more complex lifetime and must be cleaned up by the caller or in a - separate cleanup callback */ - TASK_MULTIFRAME, - TASK_COUNT -} TaskLifetime; - -typedef enum TaskKind { - TASK_RENDER, - TASK_PHYSICS, - TASK_GAMEPLAY, - TASK_ASSET, - TASK_USERLAND, - TASKKIND_COUNT -} TaskKind; - -typedef struct Task { - char* debug_name; - void* params; - bool is_done; -} Task; - -// Macro : give Params and Result structs and it creates a function that knows -// correct sizes - -typedef struct Task_ModelLoad_Params { - Str8 filepath; // filepath to the model on disk -} Task_ModelLoad_Params; -typedef struct Task_ModelLoad_Result { - Model model; -} Task_ModelLoad_Result; - -// Internally it will allocate data for each - -static bool Task_ModelLoad_Typed(Task_ModelLoad_Params* params, Task_ModelLoad_Result* result, - tpool_task_start run_task, tpool_task_on_complete on_success, - tpool_task_on_complete on_failure) { - threadpool_add_task(pool, , tpool_task_on_complete on_success, tpool_task_on_complete on_fail, - bool buffer_result_for_main_thread, void* param_data, u32 param_data_size, - u32 result_data_size) -} - -// do task -// success -void model_load_success(task_globals* globals, void* result) { - Task_ModelLoad_Result* load_res = result; - - // push into render -> renderables ? -} -// fail - -// we can define our custom task here that wraps the more verbose function pointers -static Task Task_ModelLoad(Task_ModelLoad_Params* params, Task_ModelLoad_Result* result) { - Task task; - task.debug_name = "Load Model"; - task.params = params; - - Task_ModelLoad_Typed(params, result, tpool_task_start run_task, tpool_task_on_complete on_success, - tpool_task_on_complete on_failure) - - return task; -} diff --git a/src/logos/threadpool.c b/src/logos/threadpool.c deleted file mode 100644 index 0e82d98..0000000 --- a/src/logos/threadpool.c +++ /dev/null @@ -1,141 +0,0 @@ -#include "threadpool.h" - -#include <pthread.h> - -#include "defines.h" -#include "log.h" -#include "ring_queue.h" - -static void* worker_factory(void* arg) { - threadpool_worker* worker = arg; - // INFO("Starting job thread %d", worker->id); - - // Run forever, waiting for jobs. - while (true) { - pthread_mutex_lock(&worker->pool->mutex); - pthread_cond_wait(&worker->pool->has_tasks, &worker->pool->mutex); // wait for work to be ready - - task t; - if (ring_queue_dequeue(worker->pool->task_queue, &t)) { - DEBUG("Job thread %d picked up task %d", worker->id, t.task_id); - } else { - WARN("Job thread %d didnt pick up a task as queue was empty", worker->id); - pthread_mutex_unlock(&worker->pool->mutex); - break; - } - - pthread_mutex_unlock(&worker->pool->mutex); - - // Do the work - bool result = t.do_task(t.params, t.result_data); - - // INFO("Task result was %s", result ? "success" : "failure"); - if (result) { - pthread_mutex_lock(&worker->pool->mutex); - if (t.buffer_result_for_main_thread) { - deferred_task_result dtr = { .task_id = t.task_id, - .callback = t.on_success, - .result_data = t.result_data, - .result_data_size = t.result_data_size }; - deferred_task_result_darray_push(worker->pool->results, dtr); - } else { - // call on complete from here. - } - } else { - // TODO - } - pthread_mutex_unlock(&worker->pool->mutex); - } - - return NULL; -} - -bool threadpool_create(threadpool* pool, u8 thread_count, u32 queue_size) { - INFO("Threadpool init"); - pool->next_task_id = 0; - pool->context = NULL; - - u8 num_worker_threads = thread_count; - if (thread_count > MAX_NUM_THREADS) { - ERROR_EXIT("Threadpool has a hard limit of %d threads, you tried to start one with %d", - MAX_NUM_THREADS, thread_count) - num_worker_threads = MAX_NUM_THREADS; - } - - DEBUG("creating task queue with max length %d", queue_size); - pool->task_queue = ring_queue_new(sizeof(task), queue_size, NULL); - - DEBUG("creating mutex and condition"); - pthread_mutex_init(&pool->mutex, NULL); - pthread_cond_init(&pool->has_tasks, NULL); - - pool->results = deferred_task_result_darray_new(256); - - DEBUG("Spawning %d threads for the threadpool", thread_count); - for (u8 i = 0; i < num_worker_threads; i++) { - pool->workers[i].id = i; - pool->workers[i].pool = pool; - if (pthread_create(&pool->workers[i].thread, NULL, worker_factory, &pool->workers[i]) != 0) { - FATAL("OS error creating job thread"); - return false; - }; - } - - return true; -} - -bool threadpool_add_task(threadpool* pool, tpool_task_start do_task, - tpool_task_on_complete on_success, tpool_task_on_complete on_fail, - bool buffer_result_for_main_thread, void* param_data, u32 param_data_size, - u32 result_data_size) { - void* result_data = malloc(result_data_size); - - task* work_task = malloc(sizeof(task)); - work_task->task_id = 0; - work_task->do_task = do_task; - work_task->on_success = on_success; - work_task->on_failure = on_fail; - work_task->buffer_result_for_main_thread = buffer_result_for_main_thread; - work_task->param_size = param_data_size; - work_task->params = param_data; - work_task->result_data_size = result_data_size; - work_task->result_data = result_data; - - // START critical section - if (pthread_mutex_lock(&pool->mutex) != 0) { - ERROR("Unable to get threadpool lock."); - return false; - } - - work_task->task_id = pool->next_task_id; - pool->next_task_id++; - - ring_queue_enqueue(pool->task_queue, work_task); - DEBUG("Enqueued job"); - pthread_cond_broadcast(&pool->has_tasks); - - if (pthread_mutex_unlock(&pool->mutex) != 0) { - ERROR("couldnt unlock threadpool after adding task."); - return false; // ? - } - // END critical section - - return true; -} - -void threadpool_process_results(threadpool* pool, int _num_to_process) { - pthread_mutex_lock(&pool->mutex); - size_t num_results = deferred_task_result_darray_len(pool->results); - if (num_results > 0) { - u32 _size = ((deferred_task_result*)pool->results->data)[num_results].result_data_size; - deferred_task_result res; - deferred_task_result_darray_pop(pool->results, &res); - pthread_mutex_unlock(&pool->mutex); - task_globals globals = { .pool = pool, .ctx = pool->context }; - res.callback(&globals, res.result_data); - } else { - pthread_mutex_unlock(&pool->mutex); - } -} - -void threadpool_set_ctx(threadpool* pool, void* ctx) { pool->context = ctx; }
\ No newline at end of file diff --git a/src/logos/threadpool.h b/src/logos/threadpool.h deleted file mode 100644 index 6390a38..0000000 --- a/src/logos/threadpool.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - A Threadpool has a number of "workers", each which process "tasks" -*/ -#pragma once - -#include <pthread.h> - -#include "darray.h" -#include "defines.h" -#include "ring_queue.h" - -#define MAX_NUM_THREADS 16 - -struct threadpool; -typedef struct threadpool threadpool; - -typedef struct task_globals { - threadpool* pool; - void* ctx; -} task_globals; - -/* function pointer */ -typedef bool (*tpool_task_start)(void*, void*); - -/* function pointer */ -typedef void (*tpool_task_on_complete)(task_globals*, void*); - -typedef struct threadpool_worker { - u16 id; - pthread_t thread; - threadpool* pool; // pointer back to the pool so we can get the mutex and cond -} threadpool_worker; - -typedef enum tpool_task_status { - TASK_STATUS_READY, -} task_status; - -typedef struct tpool_task { - u64 task_id; - tpool_task_start do_task; - tpool_task_on_complete on_success; - tpool_task_on_complete on_failure; - bool buffer_result_for_main_thread; - /** @brief a pointer to the parameters data that will be passed into the task. */ - void* params; - u32 param_size; - void* result_data; - u32 result_data_size; -} task; - -typedef struct deferred_task_result { - u64 task_id; - tpool_task_on_complete callback; - u32 result_data_size; - // this gets passed to the void* argument of `tpool_task_on_complete` - void* result_data; -} deferred_task_result; - -#ifndef TYPED_TASK_RESULT_ARRAY -KITC_DECL_TYPED_ARRAY(deferred_task_result) // creates "deferred_task_result_darray" -#define TYPED_TASK_RESULT_ARRAY -#endif - -struct threadpool { - ring_queue* task_queue; - pthread_mutex_t mutex; - pthread_cond_t has_tasks; - threadpool_worker workers[MAX_NUM_THREADS]; - deferred_task_result_darray* results; - u64 next_task_id; - - void* context; -}; - -/** - * @param pool where to store the created threadpool - * @param thread_count how many threads to spawn - * @param queue_size max size of task queue - */ -bool threadpool_create(threadpool* pool, u8 thread_count, u32 queue_size); -void threadpool_destroy(threadpool* pool); - -/** @brief set a context variable for the threadpool that task data has access to */ -void threadpool_set_ctx(threadpool* pool, void* ctx); - -/** - * @brief Add a task to the threadpool - */ -bool threadpool_add_task(threadpool* pool, tpool_task_start do_task, - tpool_task_on_complete on_success, tpool_task_on_complete on_fail, - bool buffer_result_for_main_thread, void* param_data, u32 param_data_size, - u32 result_data_size); - -void threadpool_process_results(threadpool* pool, int num_to_process); - -u32 Tpool_GetNumWorkers(); // how many threads are we using
\ No newline at end of file diff --git a/src/maths/geometry.h b/src/maths/geometry.h deleted file mode 100644 index 532651c..0000000 --- a/src/maths/geometry.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @file geometry.h - * @author your name (you@domain.com) - * @brief Shapes and intersections between them - * @version 0.1 - * @date 2024-02-24 - * - * @copyright Copyright (c) 2024 - */ -#pragma once - -#include "maths.h" - -// typedef struct line_3d { -// vec3 start, end; -// } line_3d; - -// typedef struct plane { -// vec3 normal; -// } plane; - -typedef struct Cuboid { - Vec3 half_extents; -} Cuboid; - -typedef struct Sphere { - f32 radius; -} Sphere; - -// typedef struct cylinder { -// f32 radius; -// f32 half_height; -// } cylinder; - -// typedef struct cone { -// f32 radius; -// f32 half_height; -// } cone; - -// TODO: -// capsule -// torus -// ray -// frustum -// conical frustum -// wedge - -// 2d... -// line -// circle diff --git a/src/maths/maths.c b/src/maths/maths.c deleted file mode 100644 index 19052fe..0000000 --- a/src/maths/maths.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "maths.h" - -#define c_static_inline - -c_static_inline Vec3 vec3_create(f32 x, f32 y, f32 z) { return (Vec3){ x, y, z }; } -c_static_inline Vec3 vec3_add(Vec3 a, Vec3 b) { return (Vec3){ a.x + b.x, a.y + b.y, a.z + b.z }; } -c_static_inline Vec3 vec3_sub(Vec3 a, Vec3 b) { return (Vec3){ a.x - b.x, a.y - b.y, a.z - b.z }; } -c_static_inline Vec3 vec3_mult(Vec3 a, f32 s) { return (Vec3){ a.x * s, a.y * s, a.z * s }; } -c_static_inline Vec3 vec3_div(Vec3 a, f32 s) { return (Vec3){ a.x / s, a.y / s, a.z / s }; } - -c_static_inline f32 vec3_len_squared(Vec3 a) { return (a.x * a.x) + (a.y * a.y) + (a.z * a.z); } -c_static_inline f32 vec3_len(Vec3 a) { return sqrtf(vec3_len_squared(a)); } -c_static_inline Vec3 vec3_negate(Vec3 a) { return (Vec3){ -a.x, -a.y, -a.z }; } -PUB c_static_inline Vec3 vec3_normalise(Vec3 a) { - f32 length = vec3_len(a); - return vec3_div(a, length); -} - -c_static_inline f32 vec3_dot(Vec3 a, Vec3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; } -c_static_inline Vec3 vec3_cross(Vec3 a, Vec3 b) { - return ( - Vec3){ .x = a.y * b.z - a.z * b.y, .y = a.z * b.x - a.x * b.z, .z = a.x * b.y - a.y * b.x }; -} - -Mat4 mat4_ident() { - return (Mat4){ .data = { 1.0, 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1.0 } }; -} - -Mat4 transform_to_mat(Transform* tf) { - Mat4 scale = mat4_scale(tf->scale); - Mat4 rotation = mat4_rotation(tf->rotation); - Mat4 translation = mat4_translation(tf->position); - // return mat4_mult(translation, mat4_mult(rotation, scale)); - return mat4_mult(mat4_mult(scale, rotation), translation); -}
\ No newline at end of file diff --git a/src/maths/maths.h b/src/maths/maths.h deleted file mode 100644 index e77b81a..0000000 --- a/src/maths/maths.h +++ /dev/null @@ -1,321 +0,0 @@ -/** - * @file maths.h - * @author your name (you@domain.com) - * @brief - * @version 0.1 - * @date 2024-02-24 - * @copyright Copyright (c) 2024 - */ -#pragma once - -#include <math.h> -#include <stdio.h> -#include "defines.h" -#include "maths_types.h" - -// #undef c_static_inline -// #define c_static_inline static - -// --- Helpers -#define deg_to_rad(x) (x * 3.14 / 180.0) -#define MIN(a, b) (a < b ? a : b) -#define MAX(a, b) (a > b ? a : b) - -// --- Vector Implementations - -// Dimension 3 -PUB c_static_inline Vec3 vec3_create(f32 x, f32 y, f32 z); -#define vec3(x, y, z) ((Vec3){ x, y, z }) -PUB c_static_inline Vec3 vec3_add(Vec3 a, Vec3 b); -PUB c_static_inline Vec3 vec3_sub(Vec3 a, Vec3 b); -PUB c_static_inline Vec3 vec3_mult(Vec3 a, f32 s); -PUB c_static_inline Vec3 vec3_div(Vec3 a, f32 s); - -PUB c_static_inline f32 vec3_len_squared(Vec3 a); -PUB c_static_inline f32 vec3_len(Vec3 a); -PUB c_static_inline Vec3 vec3_negate(Vec3 a); -PUB c_static_inline Vec3 vec3_normalise(Vec3 a); - -PUB c_static_inline f32 vec3_dot(Vec3 a, Vec3 b); -PUB c_static_inline Vec3 vec3_cross(Vec3 a, Vec3 b); - -static const Vec3 VEC3_X = vec3(1.0, 0.0, 0.0); -static const Vec3 VEC3_NEG_X = vec3(-1.0, 0.0, 0.0); -static const Vec3 VEC3_Y = vec3(0.0, 1.0, 0.0); -static const Vec3 VEC3_NEG_Y = vec3(0.0, -1.0, 0.0); -static const Vec3 VEC3_Z = vec3(0.0, 0.0, 1.0); -static const Vec3 VEC3_NEG_Z = vec3(0.0, 0.0, -1.0); -static const Vec3 VEC3_ZERO = vec3(0.0, 0.0, 0.0); -static const Vec3 VEC3_ONES = vec3(1.0, 1.0, 1.0); - -static void print_vec3(Vec3 v) { - printf("{ x: %f, y: %f, z: %f )\n", (f64)v.x, (f64)v.y, (f64)v.z); -} - -// TODO: Dimension 2 -static Vec2 vec2_create(f32 x, f32 y) { return (Vec2){ x, y }; } -#define vec2(x, y) ((Vec2){ x, y }) -static Vec2 vec2_div(Vec2 a, f32 s) { return (Vec2){ a.x / s, a.y / s }; } - -// TODO: Dimension 4 -static Vec4 vec4_create(f32 x, f32 y, f32 z, f32 w) { return (Vec4){ x, y, z, w }; } -#define vec4(x, y, z, w) (vec4_create(x, y, z, w)) -#define VEC4_ZERO ((Vec4){ .x = 0.0, .y = 0.0, .z = 0.0, .w = 0.0 }) - -// --- Quaternion Implementations - -static f32 quat_dot(Quat a, Quat b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } - -static Quat quat_normalise(Quat a) { - f32 length = sqrtf(quat_dot(a, a)); // same as len squared - - return (Quat){ a.x / length, a.y / length, a.z / length, a.w / length }; -} - -static Quat quat_ident() { return (Quat){ .x = 0.0, .y = 0.0, .z = 0.0, .w = 1.0 }; } - -static Quat quat_from_axis_angle(Vec3 axis, f32 angle, bool normalize) { - const f32 half_angle = 0.5f * angle; - f32 s = sinf(half_angle); - f32 c = cosf(half_angle); - - Quat q = (Quat){ s * axis.x, s * axis.y, s * axis.z, c }; - if (normalize) { - return quat_normalise(q); - } - return q; -} - -// TODO: grok this. -static Quat quat_slerp(Quat a, Quat b, f32 percentage) { - Quat out_quaternion; - - Quat q0 = quat_normalise(a); - Quat q1 = quat_normalise(b); - - // Compute the cosine of the angle between the two vectors. - f32 dot = quat_dot(q0, q1); - - // If the dot product is negative, slerp won't take - // the shorter path. Note that v1 and -v1 are equivalent when - // the negation is applied to all four components. Fix by - // reversing one quaternion. - if (dot < 0.0f) { - q1.x = -q1.x; - q1.y = -q1.y; - q1.z = -q1.z; - q1.w = -q1.w; - dot = -dot; - } - - const f32 DOT_THRESHOLD = 0.9995f; - if (dot > DOT_THRESHOLD) { - // If the inputs are too close for comfort, linearly interpolate - // and normalize the result. - out_quaternion = - (Quat){ q0.x + ((q1.x - q0.x) * percentage), q0.y + ((q1.y - q0.y) * percentage), - q0.z + ((q1.z - q0.z) * percentage), q0.w + ((q1.w - q0.w) * percentage) }; - - return quat_normalise(out_quaternion); - } - - // TODO: Are there math functions that take floats instead of doubles? - - // Since dot is in range [0, DOT_THRESHOLD], acos is safe - f64 theta_0 = cos((f64)dot); // theta_0 = angle between input vectors - f64 theta = theta_0 * (f64)percentage; // theta = angle between v0 and result - f64 sin_theta = sin((f64)theta); // compute this value only once - f64 sin_theta_0 = sin((f64)theta_0); // compute this value only once - - f32 s0 = - cos(theta) - (f64)dot * sin_theta / sin_theta_0; // == sin(theta_0 - theta) / sin(theta_0) - f32 s1 = sin_theta / sin_theta_0; - - return (Quat){ (q0.x * s0) + (q1.x * s1), (q0.y * s0) + (q1.y * s1), (q0.z * s0) + (q1.z * s1), - (q0.w * s0) + (q1.w * s1) }; -} - -// --- Matrix Implementations - -Mat4 mat4_ident(); - -static Mat4 mat4_translation(Vec3 position) { - Mat4 out_matrix = mat4_ident(); - out_matrix.data[12] = position.x; - out_matrix.data[13] = position.y; - out_matrix.data[14] = position.z; - return out_matrix; -} - -static Mat4 mat4_scale(Vec3 scale) { - Mat4 out_matrix = mat4_ident(); - out_matrix.data[0] = scale.x; - out_matrix.data[5] = scale.y; - out_matrix.data[10] = scale.z; - return out_matrix; -} - -// TODO: double check this -static Mat4 mat4_rotation(Quat rotation) { - Mat4 out_matrix = mat4_ident(); - Quat n = quat_normalise(rotation); - - out_matrix.data[0] = 1.0f - 2.0f * n.y * n.y - 2.0f * n.z * n.z; - out_matrix.data[1] = 2.0f * n.x * n.y - 2.0f * n.z * n.w; - out_matrix.data[2] = 2.0f * n.x * n.z + 2.0f * n.y * n.w; - - out_matrix.data[4] = 2.0f * n.x * n.y + 2.0f * n.z * n.w; - out_matrix.data[5] = 1.0f - 2.0f * n.x * n.x - 2.0f * n.z * n.z; - out_matrix.data[6] = 2.0f * n.y * n.z - 2.0f * n.x * n.w; - - out_matrix.data[8] = 2.0f * n.x * n.z - 2.0f * n.y * n.w; - out_matrix.data[9] = 2.0f * n.y * n.z + 2.0f * n.x * n.w; - out_matrix.data[10] = 1.0f - 2.0f * n.x * n.x - 2.0f * n.y * n.y; - - return out_matrix; -} - -static Mat4 mat4_mult(Mat4 lhs, Mat4 rhs) { - Mat4 out_matrix = mat4_ident(); - - const f32* m1_ptr = lhs.data; - const f32* m2_ptr = rhs.data; - f32* dst_ptr = out_matrix.data; - - for (i32 i = 0; i < 4; ++i) { - for (i32 j = 0; j < 4; ++j) { - *dst_ptr = m1_ptr[0] * m2_ptr[0 + j] + m1_ptr[1] * m2_ptr[4 + j] + m1_ptr[2] * m2_ptr[8 + j] + - m1_ptr[3] * m2_ptr[12 + j]; - dst_ptr++; - } - m1_ptr += 4; - } - - return out_matrix; -} - -static Mat4 mat4_transposed(Mat4 matrix) { - Mat4 out_matrix = mat4_ident(); - out_matrix.data[0] = matrix.data[0]; - out_matrix.data[1] = matrix.data[4]; - out_matrix.data[2] = matrix.data[8]; - out_matrix.data[3] = matrix.data[12]; - out_matrix.data[4] = matrix.data[1]; - out_matrix.data[5] = matrix.data[5]; - out_matrix.data[6] = matrix.data[9]; - out_matrix.data[7] = matrix.data[13]; - out_matrix.data[8] = matrix.data[2]; - out_matrix.data[9] = matrix.data[6]; - out_matrix.data[10] = matrix.data[10]; - out_matrix.data[11] = matrix.data[14]; - out_matrix.data[12] = matrix.data[3]; - out_matrix.data[13] = matrix.data[7]; - out_matrix.data[14] = matrix.data[11]; - out_matrix.data[15] = matrix.data[15]; - return out_matrix; -} - -#if defined(CEL_REND_BACKEND_VULKAN) -/** @brief Creates a perspective projection matrix compatible with Vulkan */ -c_static_inline Mat4 mat4_perspective(f32 fov_radians, f32 aspect_ratio, f32 near_clip, - f32 far_clip) { - f32 half_tan_fov = tanf(fov_radians * 0.5f); - Mat4 out_matrix = { .data = { 0 } }; - - out_matrix.data[0] = 1.0f / (aspect_ratio * half_tan_fov); - out_matrix.data[5] = -1.0f / half_tan_fov; // Flip Y-axis for Vulkan - out_matrix.data[10] = -((far_clip + near_clip) / (far_clip - near_clip)); - out_matrix.data[11] = -1.0f; - out_matrix.data[14] = -((2.0f * far_clip * near_clip) / (far_clip - near_clip)); - - return out_matrix; -} -#else -/** @brief Creates a perspective projection matrix */ -static inline Mat4 mat4_perspective(f32 fov_radians, f32 aspect_ratio, f32 near_clip, - f32 far_clip) { - f32 half_tan_fov = tanf(fov_radians * 0.5f); - Mat4 out_matrix = { .data = { 0 } }; - out_matrix.data[0] = 1.0f / (aspect_ratio * half_tan_fov); - out_matrix.data[5] = 1.0f / half_tan_fov; - out_matrix.data[10] = -((far_clip + near_clip) / (far_clip - near_clip)); - out_matrix.data[11] = -1.0f; - out_matrix.data[14] = -((2.0f * far_clip * near_clip) / (far_clip - near_clip)); - return out_matrix; -} -#endif - -/** @brief Creates an orthographic projection matrix */ -static inline Mat4 mat4_orthographic(f32 left, f32 right, f32 bottom, f32 top, f32 near_clip, - f32 far_clip) { - // source: kohi game engine. - Mat4 out_matrix = mat4_ident(); - - f32 lr = 1.0f / (left - right); - f32 bt = 1.0f / (bottom - top); - f32 nf = 1.0f / (near_clip - far_clip); - - out_matrix.data[0] = -2.0f * lr; - out_matrix.data[5] = -2.0f * bt; - out_matrix.data[10] = 2.0f * nf; - - out_matrix.data[12] = (left + right) * lr; - out_matrix.data[13] = (top + bottom) * bt; - out_matrix.data[14] = (far_clip + near_clip) * nf; - - return out_matrix; -} - -static inline Mat4 mat4_look_at(Vec3 position, Vec3 target, Vec3 up) { - Mat4 out_matrix; - Vec3 z_axis; - z_axis.x = target.x - position.x; - z_axis.y = target.y - position.y; - z_axis.z = target.z - position.z; - - z_axis = vec3_normalise(z_axis); - Vec3 x_axis = vec3_normalise(vec3_cross(z_axis, up)); - Vec3 y_axis = vec3_cross(x_axis, z_axis); - - out_matrix.data[0] = x_axis.x; - out_matrix.data[1] = y_axis.x; - out_matrix.data[2] = -z_axis.x; - out_matrix.data[3] = 0; - out_matrix.data[4] = x_axis.y; - out_matrix.data[5] = y_axis.y; - out_matrix.data[6] = -z_axis.y; - out_matrix.data[7] = 0; - out_matrix.data[8] = x_axis.z; - out_matrix.data[9] = y_axis.z; - out_matrix.data[10] = -z_axis.z; - out_matrix.data[11] = 0; - out_matrix.data[12] = -vec3_dot(x_axis, position); - out_matrix.data[13] = -vec3_dot(y_axis, position); - out_matrix.data[14] = vec3_dot(z_axis, position); - out_matrix.data[15] = 1.0f; - - return out_matrix; -} - -// ... - -// --- Transform Implementations - -#define TRANSFORM_DEFAULT \ - ((Transform){ .position = VEC3_ZERO, \ - .rotation = (Quat){ .x = 0., .y = 0., .z = 0., .w = 1. }, \ - .scale = 1.0, \ - .is_dirty = false }) - -static Transform transform_create(Vec3 pos, Quat rot, Vec3 scale) { - return (Transform){ .position = pos, .rotation = rot, .scale = scale, .is_dirty = true }; -} - -Mat4 transform_to_mat(Transform* tf); - -// --- Sizing asserts - -_Static_assert(alignof(Vec3) == 4, "Vec3 is 4 byte aligned"); -_Static_assert(sizeof(Vec3) == 12, "Vec3 is 12 bytes so has no padding"); - -_Static_assert(alignof(Vec4) == 4, "Vec4 is 4 byte aligned"); diff --git a/src/maths/maths_types.h b/src/maths/maths_types.h deleted file mode 100644 index 66d260d..0000000 --- a/src/maths/maths_types.h +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @file maths_types.h - * @author Omniscient - * @brief Maths types - * @date 2024-02-24 - * @copyright Copyright (c) 2024 - */ -#pragma once - -#include "defines.h" - -// --- Constants -#define PI 3.14159265358979323846 -#define HALF_PI 1.57079632679489661923 -#define TAU (2.0 * PI) - -// --- Types - -/** @brief 2D Vector */ -typedef struct Vec2 { - f32 x, y; -} Vec2; - -/** @brief 4x4 Matrix */ -typedef struct Mat4 { - // TODO: use this format for more readable code: vec4 x_axis, y_axis, z_axis, w_axis; - f32 data[16]; -} Mat4; - -/** @brief Three dimensional bounding box */ -typedef struct Bbox_3D { - Vec3 min; // minimum point of the box - Vec3 max; // maximum point of the box -} Bbox_3D; - -/** @brief 3D Axis-aligned bounding box */ -typedef Bbox_3D Aabb_3D; - -/** @brief 3D affine transformation */ -typedef struct Transform { - Vec3 position; - Quat rotation; - Vec3 scale; - bool is_dirty; -} Transform; - -typedef struct Vec4i { - i32 x, y, z, w; -} Vec4i; - -typedef struct Vec4u { - u32 x, y, z, w; -} Vec4u; - -// --- Some other types -typedef struct u32x3 { - union { - struct { - u32 x; - u32 y; - u32 z; - }; - struct { - u32 r; - u32 g; - u32 b; - }; - }; -} u32x3; -#define u32x3(x, y, z) ((u32x3){ x, y, z }) - -typedef struct u32x2 { - u32 x; - u32 y; -} u32x2; -#define u32x2(x, y) ((u32x2){ x, y }) - -// Type aliass - -typedef struct Vec2 f32x2; -#define f32x2(x, y) ((f32x2){ x, y }) - -typedef struct Vec3 f32x3; -#define f32x3(x, y, z) ((f32x3){ x, y, z }) diff --git a/src/maths/primitives.c b/src/maths/primitives.c deleted file mode 100644 index c24d1e2..0000000 --- a/src/maths/primitives.c +++ /dev/null @@ -1,343 +0,0 @@ -#include "primitives.h" -#include "colours.h" -#include "log.h" -#include "maths.h" -#include "maths_types.h" -#include "ral_types.h" -#include "render_types.h" - -// --- Helpers - -void push_triangle(u32_darray* arr, u32 i0, u32 i1, u32 i2) { - u32_darray_push(arr, i0); - u32_darray_push(arr, i1); - u32_darray_push(arr, i2); -} - -Vec3 plane_vertex_positions[] = { - (Vec3){ -0.5, 0, -0.5 }, - (Vec3){ 0.5, 0, -0.5 }, - (Vec3){ -0.5, 0, 0.5 }, - (Vec3){ 0.5, 0, 0.5 }, -}; - -Geometry Geo_CreatePlane(f32x2 extents, u32 tiling_u, u32 tiling_v) { - CASSERT(tiling_u >= 1 && tiling_v >= 1); - Vertex_darray* vertices = Vertex_darray_new(4); - u32_darray* indices = u32_darray_new(vertices->len); - - Vec3 vert_pos[4]; - memcpy(&vert_pos, plane_vertex_positions, sizeof(plane_vertex_positions)); - for (int i = 0; i < 4; i++) { - vert_pos[i].x *= extents.x; - vert_pos[i].z *= extents.y; - } - VERT_3D(vertices, vert_pos[0], VEC3_Y, vec2(0, 0)); // back left - VERT_3D(vertices, vert_pos[1], VEC3_Y, vec2(1 * tiling_u, 0 * tiling_v)); // back right - VERT_3D(vertices, vert_pos[2], VEC3_Y, vec2(0, 1 * tiling_v)); // front left - VERT_3D(vertices, vert_pos[3], VEC3_Y, vec2(1 * tiling_u, 1 * tiling_v)); // front right - - // push_triangle(indices, 0, 1, 2); - // push_triangle(indices, 2, 1, 3); - push_triangle(indices, 2, 1, 0); - push_triangle(indices, 1, 2, 3); - - for (int i = 0; i < 4; i++) { - printf("Vertex %d: (%f, %f, %f)\n", i, vert_pos[i].x, vert_pos[i].y, vert_pos[i].z); - } - - Geometry geo = { .format = VERTEX_STATIC_3D, - .vertices = vertices, - .has_indices = true, - .index_count = indices->len, - .indices = indices }; - - return geo; -} - -Geometry Geo_CreateCuboid(f32x3 extents) { - Vertex_darray* vertices = Vertex_darray_new(36); - - // back faces - VERT_3D(vertices, BACK_TOP_RIGHT, VEC3_NEG_Z, vec2(1, 0)); - VERT_3D(vertices, BACK_BOT_LEFT, VEC3_NEG_Z, vec2(0, 1)); - VERT_3D(vertices, BACK_TOP_LEFT, VEC3_NEG_Z, vec2(0, 0)); - VERT_3D(vertices, BACK_TOP_RIGHT, VEC3_NEG_Z, vec2(1, 0)); - VERT_3D(vertices, BACK_BOT_RIGHT, VEC3_NEG_Z, vec2(1, 1)); - VERT_3D(vertices, BACK_BOT_LEFT, VEC3_NEG_Z, vec2(0, 1)); - - // front faces - VERT_3D(vertices, FRONT_BOT_LEFT, VEC3_Z, vec2(0, 1)); - VERT_3D(vertices, FRONT_TOP_RIGHT, VEC3_Z, vec2(1, 0)); - VERT_3D(vertices, FRONT_TOP_LEFT, VEC3_Z, vec2(0, 0)); - VERT_3D(vertices, FRONT_BOT_LEFT, VEC3_Z, vec2(0, 1)); - VERT_3D(vertices, FRONT_BOT_RIGHT, VEC3_Z, vec2(1, 1)); - VERT_3D(vertices, FRONT_TOP_RIGHT, VEC3_Z, vec2(1, 0)); - - // top faces - VERT_3D(vertices, BACK_TOP_LEFT, VEC3_Y, vec2(0, 0)); - VERT_3D(vertices, FRONT_TOP_LEFT, VEC3_Y, vec2(0, 1)); - VERT_3D(vertices, FRONT_TOP_RIGHT, VEC3_Y, vec2(1, 1)); - VERT_3D(vertices, BACK_TOP_LEFT, VEC3_Y, vec2(0, 0)); - VERT_3D(vertices, FRONT_TOP_RIGHT, VEC3_Y, vec2(1, 1)); - VERT_3D(vertices, BACK_TOP_RIGHT, VEC3_Y, vec2(1, 0)); - - // bottom faces - VERT_3D(vertices, BACK_BOT_LEFT, VEC3_NEG_Y, vec2(0, 1)); - VERT_3D(vertices, FRONT_BOT_RIGHT, VEC3_NEG_Y, vec2(1, 1)); - VERT_3D(vertices, FRONT_BOT_LEFT, VEC3_NEG_Y, vec2(0, 1)); - VERT_3D(vertices, BACK_BOT_LEFT, VEC3_NEG_Y, vec2(0, 1)); - VERT_3D(vertices, BACK_BOT_RIGHT, VEC3_NEG_Y, vec2(1, 1)); - VERT_3D(vertices, FRONT_BOT_RIGHT, VEC3_NEG_Y, vec2(0, 1)); - - // right faces - VERT_3D(vertices, FRONT_TOP_RIGHT, VEC3_X, vec2(0, 0)); - VERT_3D(vertices, BACK_BOT_RIGHT, VEC3_X, vec2(1, 1)); - VERT_3D(vertices, BACK_TOP_RIGHT, VEC3_X, vec2(1, 0)); - VERT_3D(vertices, BACK_BOT_RIGHT, VEC3_X, vec2(1, 1)); - VERT_3D(vertices, FRONT_TOP_RIGHT, VEC3_X, vec2(0, 0)); - VERT_3D(vertices, FRONT_BOT_RIGHT, VEC3_X, vec2(0, 1)); - - // left faces - VERT_3D(vertices, FRONT_TOP_LEFT, VEC3_NEG_X, vec2(0, 0)); - VERT_3D(vertices, BACK_TOP_LEFT, VEC3_NEG_X, vec2(0, 0)); - VERT_3D(vertices, BACK_BOT_LEFT, VEC3_NEG_X, vec2(0, 0)); - VERT_3D(vertices, BACK_BOT_LEFT, VEC3_NEG_X, vec2(0, 0)); - VERT_3D(vertices, FRONT_BOT_LEFT, VEC3_NEG_X, vec2(0, 0)); - VERT_3D(vertices, FRONT_TOP_LEFT, VEC3_NEG_X, vec2(0, 0)); - - u32_darray* indices = u32_darray_new(vertices->len); - - for (u32 i = 0; i < vertices->len; i++) { - u32_darray_push(indices, i); - vertices->data[i].static_3d.position = - vec3_sub(vertices->data[i].static_3d.position, - vec3(0.5, 0.5, 0.5)); // make center of the cube is the origin of mesh space - } - - Geometry geo = { - .format = VERTEX_STATIC_3D, - .vertices = vertices, - .has_indices = true, - .index_count = indices->len, - .indices = indices, // FIXME: make darray methods that return stack allocated struct - }; - - return geo; -} - -// --- Spheres - -Vec3 spherical_to_cartesian_coords(f32 rho, f32 theta, f32 phi) { - f32 x = rho * sin(phi) * cos(theta); - f32 y = rho * cos(phi); - f32 z = rho * sin(phi) * sin(theta); - return vec3(x, y, z); -} - -Geometry Geo_CreateUVsphere(f32 radius, u32 north_south_lines, u32 east_west_lines) { - assert(east_west_lines >= 3); // sphere will be degenerate and look gacked without at least 3 - assert(north_south_lines >= 3); - - Vertex_darray* vertices = Vertex_darray_new(2 + (east_west_lines - 1) * north_south_lines); - - // Create a UV sphere with spherical coordinates - // a point P on the unit sphere can be represented P(r, theta, phi) - // for each vertex we must convert that to a cartesian R3 coordinate - - // Top point - Vertex top = { .static_3d = { .position = vec3(0, radius, 0), - .normal = vec3_normalise(vec3(0, radius, 0)), - .tex_coords = vec2(0, 0) } }; - Vertex_darray_push(vertices, top); - - // parallels - for (u32 i = 0; i < (east_west_lines - 1); i++) { - // phi should range from 0 to pi - f32 phi = PI * (((f32)i + 1) / (f32)east_west_lines); - - // meridians - for (u32 j = 0; j < east_west_lines; j++) { - // theta should range from 0 to 2PI - f32 theta = TAU * ((f32)j / (f32)north_south_lines); - Vec3 position = spherical_to_cartesian_coords(radius, theta, phi); - // f32 d = vec3_len(position); - // print_vec3(position); - // printf("Phi %f Theta %f d %d\n", phi, theta, d); - // assert(d == radius); // all points on the sphere should be 'radius' away from the origin - Vertex v = { .static_3d = { - .position = position, - .normal = - vec3_normalise(position), // normal vector on sphere is same as position - .tex_coords = vec2(0, 0) // TODO - } }; - Vertex_darray_push(vertices, v); - } - } - - // Bottom point - Vertex bot = { .static_3d = { .position = vec3(0, -radius, 0), - .normal = vec3_normalise(vec3(0, -radius, 0)), - .tex_coords = vec2(0, 0) } }; - Vertex_darray_push(vertices, bot); - - u32_darray* indices = u32_darray_new(1); - - // top bottom rings - for (u32 i = 0; i < north_south_lines; i++) { - u32 i1 = i + 1; - u32 i2 = (i + 1) % north_south_lines + 1; - push_triangle(indices, 0, i2, i1); - /* TRACE("Push triangle (%.2f %.2f %.2f)->(%.2f %.2f %.2f)->(%.2f %.2f %.2f)\n", */ - /* vertices->data[0].static_3d.position.x, vertices->data[0].static_3d.position.y, */ - /* vertices->data[0].static_3d.position.z, vertices->data[i1].static_3d.position.x, */ - /* vertices->data[i1].static_3d.position.y, vertices->data[i1].static_3d.position.z, */ - /* vertices->data[i2].static_3d.position.x, vertices->data[i2].static_3d.position.y, */ - /* vertices->data[i2].static_3d.position.z); */ - u32 bot = vertices->len - 1; - u32 i3 = i + north_south_lines * (east_west_lines - 2) + 1; - u32 i4 = (i + 1) % north_south_lines + north_south_lines * (east_west_lines - 2) + 1; - push_triangle(indices, bot, i3, i4); - } - - // quads - for (u32 i = 0; i < east_west_lines - 2; i++) { - u32 ring_start = i * north_south_lines + 1; - u32 next_ring_start = (i + 1) * north_south_lines + 1; - /* printf("ring start %d next ring start %d\n", ring_start, next_ring_start); */ - /* print_vec3(vertices->data[ring_start].static_3d.position); */ - /* print_vec3(vertices->data[next_ring_start].static_3d.position); */ - for (u32 j = 0; j < north_south_lines; j++) { - u32 i0 = ring_start + j; - u32 i1 = next_ring_start + j; - u32 i2 = ring_start + (j + 1) % north_south_lines; - u32 i3 = next_ring_start + (j + 1) % north_south_lines; - push_triangle(indices, i0, i2, i1); - /* TRACE("Push triangle (%.2f %.2f %.2f)->(%.2f %.2f %.2f)->(%.2f %.2f %.2f)\n", */ - /* vertices->data[i0].static_3d.position.x, vertices->data[i0].static_3d.position.y, */ - /* vertices->data[i0].static_3d.position.z, vertices->data[i1].static_3d.position.x, */ - /* vertices->data[i1].static_3d.position.y, vertices->data[i1].static_3d.position.z, */ - /* vertices->data[i2].static_3d.position.x, vertices->data[i2].static_3d.position.y, */ - /* vertices->data[i2].static_3d.position.z); */ - push_triangle(indices, i1, i2, i3); - } - } - - Geometry geo = { - .format = VERTEX_STATIC_3D, - .vertices = vertices, - .has_indices = true, - .index_count = indices->len, - .indices = indices, - }; - - return geo; -} - -Geometry Geo_CreateCone(f32 radius, f32 height, u32 resolution) { - Vertex_darray* vertices = Vertex_darray_new((resolution + 1) * 2); - u32_darray* indices = u32_darray_new(resolution * 2 * 3); - - // TODO: decide how UVs are unwrapped - - // tip - VERT_3D(vertices, vec3(0.0, height, 0.0), VEC3_Y, vec2(0, 0)); - - // sides - f32 step = TAU / resolution; - - for (u32 i = 0; i < resolution; i++) { - f32 x = cos(step * i) * radius; - f32 z = sin(step * i) * radius; - Vec3 pos = vec3(x, 0.0, z); - Vec3 tip_to_vertex = vec3_sub(pos, vertices->data[0].static_3d.position); - Vec3 center_to_vertex = pos; - Vec3 tangent = vec3_cross(VEC3_Y, center_to_vertex); - Vec3 normal_dir = vec3_cross(tangent, tip_to_vertex); - Vec3 normal = vec3_normalise(normal_dir); - VERT_3D(vertices, pos, normal, vec2(0, 0)); - } - for (u32 i = 1; i < resolution; i++) { - push_triangle(indices, 0, i + 1, i); - } - push_triangle(indices, 0, 1, resolution); - - // base center - u32 center_idx = vertices->len; - VERT_3D(vertices, VEC3_ZERO, VEC3_NEG_Y, vec2(0, 0)); - - // base circle - for (u32 i = 0; i < resolution; i++) { - f32 x = cos(step * i) * radius; - f32 z = sin(step * i) * radius; - VERT_3D(vertices, vec3(x, 0.0, z), VEC3_NEG_Z, vec2(0, 0)); - } - for (u32 i = 1; i < resolution; i++) { - push_triangle(indices, center_idx, center_idx + i, center_idx + i + 1); - } - push_triangle(indices, center_idx, center_idx + resolution, center_idx + 1); - - Geometry geo = { - .format = VERTEX_STATIC_3D, - .vertices = vertices, - .has_indices = true, - .index_count = indices->len, - .indices = indices, - }; - return geo; -} - -Geometry Geo_CreateCylinder(f32 radius, f32 height, u32 resolution) { - Vertex_darray* vertices = Vertex_darray_new(1); - u32_darray* indices = u32_darray_new(1); - - f32 step = TAU / resolution; - - // bot cap - VERT_3D(vertices, VEC3_ZERO, VEC3_NEG_Y, vec2(0, 0)); - for (u32 i = 0; i < resolution; i++) { - VERT_3D(vertices, vec3(cos(step * i) * radius, 0.0, sin(step * i) * radius), VEC3_NEG_Y, - vec2(0, 0)); - } - for (u32 i = 1; i < resolution; i++) { - push_triangle(indices, 0, i, i + 1); - } - push_triangle(indices, 0, resolution, 1); - - // top cap - u32 center_idx = vertices->len; - VERT_3D(vertices, vec3(0.0, height, 0.0), VEC3_Y, vec2(0, 0)); - for (u32 i = 0; i < resolution; i++) { - VERT_3D(vertices, vec3(cos(step * i) * radius, height, sin(step * i) * radius), VEC3_Y, - vec2(0, 0)); - } - for (u32 i = 1; i < resolution; i++) { - push_triangle(indices, center_idx, center_idx + i + 1, center_idx + i); - } - push_triangle(indices, center_idx, center_idx + 1, center_idx + resolution); - - // sides - u32 sides_start = vertices->len; - for (u32 i = 0; i < resolution; i++) { - f32 x = cos(step * i) * radius; - f32 z = sin(step * i) * radius; - // top then bottom - VERT_3D(vertices, vec3(x, height, z), vec3_normalise(vec3(x, 0.0, z)), vec2(0, 0)); - VERT_3D(vertices, vec3(x, 0.0, z), vec3_normalise(vec3(x, 0.0, z)), vec2(0, 0)); - } - for (u32 i = 0; i < resolution; i++) { - u32 current = sides_start + i * 2; - u32 next = sides_start + ((i + 1) % resolution) * 2; - push_triangle(indices, current, next, current + 1); - push_triangle(indices, current + 1, next, next + 1); - } - - Geometry geo = { - .format = VERTEX_STATIC_3D, - .vertices = vertices, - .has_indices = true, - .index_count = indices->len, - .indices = indices, - }; - return geo; -} diff --git a/src/maths/primitives.h b/src/maths/primitives.h deleted file mode 100644 index 4965545..0000000 --- a/src/maths/primitives.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include <assert.h> -#include <stdlib.h> -#include "core.h" -#include "maths_types.h" -#include "render_types.h" - -Geometry Geo_CreatePlane(f32x2 extents, u32 tiling_u, u32 tiling_v); -Geometry Geo_CreateCuboid(f32x3 extents); -Geometry Geo_CreateCylinder(f32 radius, f32 height, u32 resolution); -Geometry Geo_CreateCone(f32 radius, f32 height, u32 resolution); -Geometry Geo_CreateUVsphere(f32 radius, u32 north_south_lines, u32 east_west_lines); -Geometry Geo_CreateIcosphere(f32 radius, f32 n_subdivisions); - -static const Vec3 BACK_BOT_LEFT = (Vec3){ 0, 0, 0 }; -static const Vec3 BACK_BOT_RIGHT = (Vec3){ 1, 0, 0 }; -static const Vec3 BACK_TOP_LEFT = (Vec3){ 0, 1, 0 }; -static const Vec3 BACK_TOP_RIGHT = (Vec3){ 1, 1, 0 }; -static const Vec3 FRONT_BOT_LEFT = (Vec3){ 0, 0, 1 }; -static const Vec3 FRONT_BOT_RIGHT = (Vec3){ 1, 0, 1 }; -static const Vec3 FRONT_TOP_LEFT = (Vec3){ 0, 1, 1 }; -static const Vec3 FRONT_TOP_RIGHT = (Vec3){ 1, 1, 1 }; - -#define VERT_3D(arr, pos, norm, uv) \ - { \ - Vertex v = { .static_3d = { .position = pos, .normal = norm, .tex_coords = uv } }; \ - Vertex_darray_push(arr, v); \ - }
\ No newline at end of file diff --git a/src/physics.h b/src/physics.h deleted file mode 100644 index 134f08b..0000000 --- a/src/physics.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "geometry.h" -#include "maths_types.h" - -// 'system' means that it gets called per frame - -typedef struct physics_settings { - f32 gravity_strength; -} physics_settings; - -// What else do I need? -// intersection methods - -typedef struct physics_world { - physics_settings settings; -} physics_world; - -physics_world physics_init(physics_settings settings); -void physics_shutdown(physics_world* phys_world); - -/** @brief perform one or more simulation steps */ -void physics_system_update(physics_world* phys_world, f64 deltatime); - -// enum ColliderType { -// CuboidCollider, -// SphereCollider, -// }; - -/** @brief Oriented Bounding Box */ -typedef struct OBB { - Vec3 center; - Bbox_3D bbox; - Quat rotation; -} OBB; - -PUB void Debug_DrawOBB(OBB obb); - -/** @brief generic collider structure */ -typedef struct Collider { - u64 id; // ? Replace with handle? - OBB shape; // NOTE: We're only supporting the one collider type for now - bool on_ground; -} Collider; diff --git a/src/platform/file.c b/src/platform/file.c deleted file mode 100644 index 91daa4f..0000000 --- a/src/platform/file.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "file.h" - -#include <errno.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> - -#include "log.h" -#include "mem.h" -#include "str.h" - -const char* string_from_file(const char* path) { - FILE* f = fopen(path, "rb"); - if (f == NULL) { - ERROR("Error reading file: %s. errno: %d", path, errno); - return NULL; - } - if (ferror(f)) { - ERROR("Error reading file: %s. errno: %d", path, errno); - return NULL; - } - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - rewind(f); - - char* string = malloc(fsize + 1); - fread(string, fsize, 1, f); - fclose(f); - - string[fsize] = '\0'; - - return string; -} - -str8_opt str8_from_file(arena* a, Str8 path) { - char* p = cstr(a, path); - str8_opt result = { .has_value = false }; - - FILE* f = fopen(p, "rb"); - if (f == NULL) { - ERROR("Error reading file: %s. errno: %d", path, errno); - return result; - } - if (ferror(f)) { - ERROR("Error reading file: %s. errno: %d", path, errno); - return result; - } - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - rewind(f); - - u8* raw = arena_alloc(a, fsize + 1); - Str8 contents = Str8_create(raw, fsize); - contents.buf[contents.len] = '\0'; - - fread(raw, fsize, 1, f); - fclose(f); - result.contents = contents; - result.has_value = true; - - return result; -} - -FileData load_spv_file(const char* path) { - FILE* f = fopen(path, "rb"); - if (f == NULL) { - perror("Error opening file"); - return (FileData){ NULL, 0 }; - } - - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - rewind(f); - - char* data = (char*)malloc(fsize); - if (data == NULL) { - perror("Memory allocation failed"); - fclose(f); - return (FileData){ NULL, 0 }; - } - - size_t bytesRead = fread(data, 1, fsize, f); - if (bytesRead < fsize) { - perror("Failed to read the entire file"); - free(data); - fclose(f); - return (FileData){ NULL, 0 }; - } - - fclose(f); - return (FileData){ data, bytesRead }; -} diff --git a/src/platform/file.h b/src/platform/file.h deleted file mode 100644 index 5e5e1e1..0000000 --- a/src/platform/file.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @file file.h - * @brief File I/O utilities - * @date 2024-02-24 - * @copyright Copyright (c) 2024 - */ -#pragma once - -#include "defines.h" -#include "str.h" - -typedef struct str8_opt { - Str8 contents; - bool has_value; -} str8_opt; - -const char* string_from_file(const char* path); - -str8_opt str8_from_file(arena* a, Str8 path); - -typedef struct { - char* data; - size_t size; -} FileData; - -FileData load_spv_file(const char* path); diff --git a/src/platform/platform.h b/src/platform/platform.h deleted file mode 100644 index c2be630..0000000 --- a/src/platform/platform.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "defines.h" -#include "str.h" - -// -- Paths -typedef struct path_opt { - Str8 path; - bool has_value; -} path_opt; - -// TODO: convert to using str8 -// TODO: use uppercase code style -path_opt path_parent(arena* a, const char* path); - -// --- Threads -typedef struct CelThread CelThread; - -CelThread Thread_Create(); -void Thread_Destroy(CelThread* thread); - -// --- Mutexes -typedef struct CelMutex CelMutex; - -CelMutex Mutex_Create(); -void Mutex_Destroy(CelMutex* mutex); - -/** @brief Blocks until the mutex can be acquired. if returns false then an error occurred and can - * be checked (TODO) */ -bool Mutex_Lock(CelMutex* mutex); - -/** @brief Tries to acquire the mutex like `mutex_lock` but returns immediately if the mutex has - * already been locked */ -bool Mutex_TryLock(CelMutex* mutex); - -/** @brief Releases a mutex. If it is already unlocked then does nothing */ -void Mutex_Unlock(CelMutex* mutex); diff --git a/src/platform/platform_unix.c b/src/platform/platform_unix.c deleted file mode 100644 index 86ac170..0000000 --- a/src/platform/platform_unix.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "platform.h" - -#if defined(CEL_PLATFORM_LINUX) || defined(CEL_PLATFORM_MAC) - -#include <libgen.h> -#include <string.h> - -path_opt path_parent(arena* a, const char* path) { - // Duplicate the string because dirname doesnt like const literals - char* path_copy = arena_alloc(a, strlen(path) + 1); - strcpy(path_copy, path); - char* path_dirname = dirname(path_copy); - return (path_opt){ .path = Str8_cstr_view(path_dirname), .has_value = true }; -} - -#endif diff --git a/src/platform/platform_windows.c b/src/platform/platform_windows.c deleted file mode 100644 index 21ef359..0000000 --- a/src/platform/platform_windows.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "platform.h" - -#if defined(CEL_PLATFORM_WINDOWS) - -#include <shlwapi.h> -#include <windows.h> -#pragma comment(lib, "Shlwapi.lib") - -path_opt path_parent(arena* a, const char* path) { - // Duplicate the string because PathRemoveFileSpec mutates in-place - size_t len = strlen(path) + 1; - char* path_copy = arena_alloc(a, len); - strcpy_s(path_copy, len, path); - - if (PathRemoveFileSpecA(path_copy)) { - return (path_opt){ .path = Str8_cstr_view(path_copy), .has_value = true }; - } else { - return (path_opt){ .has_value = false }; - } -} - -#endif diff --git a/src/ral/README.md b/src/ral/README.md deleted file mode 100644 index f66b95a..0000000 --- a/src/ral/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# RAL - -**Render Abstraction Layer** is a thin abstraction over graphics APIs. Everything in `render` builds on top of the code in -this folder in order to be API-agnostic. It also makes writing graphics code easier as it smooths over some of the discrepancies -between APIs like texture/buffer creation and updating shader values.
\ No newline at end of file diff --git a/src/ral/backends/metal/backend_metal.h b/src/ral/backends/metal/backend_metal.h deleted file mode 100644 index e69de29..0000000 --- a/src/ral/backends/metal/backend_metal.h +++ /dev/null diff --git a/src/ral/backends/opengl/backend_opengl.c b/src/ral/backends/opengl/backend_opengl.c deleted file mode 100644 index 613d7e1..0000000 --- a/src/ral/backends/opengl/backend_opengl.c +++ /dev/null @@ -1,449 +0,0 @@ -#include "backend_opengl.h" -#include "colours.h" -#include "maths_types.h" -#if defined(CEL_REND_BACKEND_OPENGL) -#include <assert.h> -#include "log.h" -#include "mem.h" -#include "opengl_helpers.h" -#include "ral_common.h" -#include "ral_impl.h" -#include "ral_types.h" - -#include <glad/glad.h> -#include <glfw3.h> - -typedef struct OpenglCtx { - GLFWwindow* window; - arena pool_arena; - GPU_Swapchain swapchain; - GPU_CmdEncoder main_encoder; - GPU_BackendPools gpu_pools; - ResourcePools* resource_pools; -} OpenglCtx; - -static OpenglCtx context; - -bool GPU_Backend_Init(const char* window_name, struct GLFWwindow* window, - struct ResourcePools* res_pools) { - INFO("loading OpenGL backend"); - - memset(&context, 0, sizeof(context)); - context.window = window; - - size_t pool_buffer_size = 1024 * 1024; - context.pool_arena = arena_create(malloc(pool_buffer_size), pool_buffer_size); - - BackendPools_Init(&context.pool_arena, &context.gpu_pools); - context.resource_pools = res_pools; - - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); - - // glad: load all opengl function pointers - if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { - ERROR("Failed to initialise GLAD \n"); - return false; - } - - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - - context.swapchain = (GPU_Swapchain){ .dimensions = u32x2(1000, 1000) }; - - return true; -} - -// All of these are no-ops in OpenGL -void GPU_Backend_Shutdown() { /* TODO */ } -bool GPU_Device_Create(GPU_Device* out_device) { return true; } -void GPU_Device_Destroy(GPU_Device* device) {} -bool GPU_Swapchain_Create(GPU_Swapchain* out_swapchain) { return true; } -void GPU_Swapchain_Destroy(GPU_Swapchain* swapchain) {} -void GPU_CmdEncoder_Destroy(GPU_CmdEncoder* encoder) {} - -void GPU_CmdEncoder_BeginRender(GPU_CmdEncoder* encoder, GPU_Renderpass* renderpass) { - glBindFramebuffer(GL_FRAMEBUFFER, renderpass->fbo); - // rgba clear_colour = STONE_800; - // glClearColor(clear_colour.r, clear_colour.g, clear_colour.b, 1.0f); - // if (renderpass->description.has_depth_stencil) { - // glClear(GL_DEPTH_BUFFER_BIT); - // } else { - // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // } -} - -void GPU_CmdEncoder_EndRender(GPU_CmdEncoder* encoder) { glBindFramebuffer(GL_FRAMEBUFFER, 0); } - -GPU_CmdEncoder* GPU_GetDefaultEncoder() { return &context.main_encoder; } -void GPU_QueueSubmit(GPU_CmdBuffer* cmd_buffer) {} - -void GPU_Swapchain_Resize(i32 new_width, i32 new_height) { - context.swapchain.dimensions = u32x2(new_width, new_height); -} - -u32x2 GPU_Swapchain_GetDimensions() { return context.swapchain.dimensions; } - -GPU_Renderpass* GPU_Renderpass_Create(GPU_RenderpassDesc description) { - // allocate new pass - GPU_Renderpass* renderpass = Renderpass_pool_alloc(&context.gpu_pools.renderpasses, NULL); - renderpass->description = description; - - if (!description.default_framebuffer) { - // If we're not using the default framebuffer we need to generate a new one - GLuint gl_fbo_id; - glGenFramebuffers(1, &gl_fbo_id); - renderpass->fbo = gl_fbo_id; - } else { - renderpass->fbo = OPENGL_DEFAULT_FRAMEBUFFER; - assert(!description.has_color_target); - assert(!description.has_depth_stencil); - } - glBindFramebuffer(GL_FRAMEBUFFER, renderpass->fbo); - - if (description.has_color_target && !description.default_framebuffer) { - GPU_Texture* colour_attachment = TEXTURE_GET(description.color_target); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - colour_attachment->id, 0); - } - if (description.has_depth_stencil && !description.default_framebuffer) { - GPU_Texture* depth_attachment = TEXTURE_GET(description.depth_stencil); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_attachment->id, - 0); - } - - if (description.has_depth_stencil && !description.has_color_target) { - glDrawBuffer(GL_NONE); - glReadBuffer(GL_NONE); - } - - glBindFramebuffer(GL_FRAMEBUFFER, 0); // reset to default framebuffer - - return renderpass; -} - -void GPU_Renderpass_Destroy(GPU_Renderpass* pass) { glDeleteFramebuffers(1, &pass->fbo); } - -GPU_Pipeline* GPU_GraphicsPipeline_Create(GraphicsPipelineDesc description, - GPU_Renderpass* renderpass) { - GPU_Pipeline* pipeline = Pipeline_pool_alloc(&context.gpu_pools.pipelines, NULL); - - // Create shader program - u32 shader_id = shader_create_separate(description.vs.filepath.buf, description.fs.filepath.buf); - pipeline->shader_id = shader_id; - - // Vertex format - pipeline->vertex_desc = description.vertex_desc; - - // Allocate uniform buffers if needed - u32 ubo_count = 0; - // printf("data layouts %d\n", description.data_layouts_count); - for (u32 layout_i = 0; layout_i < description.data_layouts_count; layout_i++) { - ShaderDataLayout sdl = description.data_layouts[layout_i]; - TRACE("Got shader data layout %d's bindings! . found %d", layout_i, sdl.binding_count); - - for (u32 binding_j = 0; binding_j < sdl.binding_count; binding_j++) { - u32 binding_id = binding_j; - assert(binding_id < MAX_PIPELINE_UNIFORM_BUFFERS); - ShaderBinding binding = sdl.bindings[binding_j]; - // Do I want Buffer vs Bytes? - if (binding.kind == BINDING_BYTES) { - static u32 s_binding_point = 0; - BufferHandle ubo_handle = GPU_BufferCreate(binding.data.bytes.size, BUFFER_UNIFORM, - BUFFER_FLAG_GPU, NULL); // no data right now - pipeline->uniform_bindings[ubo_count++] = ubo_handle; - GPU_Buffer* ubo_buf = BUFFER_GET(ubo_handle); - - i32 blockIndex = glGetUniformBlockIndex(pipeline->shader_id, binding.label); - printf("Block index for %s: %d", binding.label, blockIndex); - if (blockIndex < 0) { - WARN("Couldn't retrieve block index for uniform block '%s'", binding.label); - } else { - // DEBUG("Retrived block index %d for %s", blockIndex, binding.label); - } - u32 blocksize; - glGetActiveUniformBlockiv(pipeline->shader_id, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, - &blocksize); - printf("\t with size %d bytes\n", blocksize); - - glBindBufferBase(GL_UNIFORM_BUFFER, s_binding_point, ubo_buf->id.ubo); - if (blockIndex != GL_INVALID_INDEX) { - glUniformBlockBinding(pipeline->shader_id, blockIndex, s_binding_point); - } - ubo_buf->ubo_binding_point = s_binding_point++; - ubo_buf->name = binding.label; - assert(s_binding_point < GL_MAX_UNIFORM_BUFFER_BINDINGS); - } - } - } - pipeline->uniform_count = ubo_count; - - pipeline->renderpass = renderpass; - pipeline->wireframe = description.wireframe; - - return pipeline; -} - -void GraphicsPipeline_Destroy(GPU_Pipeline* pipeline) {} - -GPU_CmdEncoder GPU_CmdEncoder_Create() { - GPU_CmdEncoder encoder = { 0 }; - return encoder; -} - -BufferHandle GPU_BufferCreate(u64 size, GPU_BufferType buf_type, GPU_BufferFlags flags, - const void* data) { - // "allocating" the cpu-side buffer struct - BufferHandle handle; - GPU_Buffer* buffer = Buffer_pool_alloc(&context.resource_pools->buffers, &handle); - buffer->size = size; - buffer->vao = 0; - - // Opengl buffer - GLuint gl_buffer_id; - glGenBuffers(1, &gl_buffer_id); - - GLenum gl_buf_type; - GLenum gl_buf_usage = GL_STATIC_DRAW; - - switch (buf_type) { - case BUFFER_UNIFORM: - DEBUG("Creating Uniform buffer"); - gl_buf_type = GL_UNIFORM_BUFFER; - /* gl_buf_usage = GL_DYNAMIC_DRAW; */ - buffer->id.ubo = gl_buffer_id; - break; - case BUFFER_DEFAULT: - case BUFFER_VERTEX: - DEBUG("Creating Vertex buffer"); - gl_buf_type = GL_ARRAY_BUFFER; - buffer->id.vbo = gl_buffer_id; - break; - case BUFFER_INDEX: - DEBUG("Creating Index buffer"); - gl_buf_type = GL_ELEMENT_ARRAY_BUFFER; - buffer->id.ibo = gl_buffer_id; - break; - default: - WARN("Unimplemented gpu_buffer_type provided %s", buffer_type_names[buf_type]); - break; - } - // bind buffer - glBindBuffer(gl_buf_type, gl_buffer_id); - - if (data) { - TRACE("Upload data (%d bytes) as part of buffer creation", size); - glBufferData(gl_buf_type, buffer->size, data, gl_buf_usage); - } else { - TRACE("Allocating but not uploading (%d bytes)", size); - glBufferData(gl_buf_type, buffer->size, NULL, gl_buf_usage); - } - - glBindBuffer(gl_buf_type, 0); - - return handle; -} - -void GPU_BufferDestroy(BufferHandle handle) { glDeleteBuffers(1, &handle.raw); } - -TextureHandle GPU_TextureCreate(TextureDesc desc, bool create_view, const void* data) { - // "allocating" the cpu-side struct - TextureHandle handle; - GPU_Texture* texture = Texture_pool_alloc(&context.resource_pools->textures, &handle); - DEBUG("Allocated texture with handle %d", handle.raw); - - GLuint gl_texture_id; - glGenTextures(1, &gl_texture_id); - texture->id = gl_texture_id; - - GLenum gl_tex_type = opengl_tex_type(desc.tex_type); - texture->type = desc.tex_type; - printf("Creating texture of type %s\n", texture_type_names[desc.tex_type]); - glBindTexture(gl_tex_type, gl_texture_id); - - GLint internal_format; - if (desc.format == TEXTURE_FORMAT_DEPTH_DEFAULT) { - internal_format = GL_DEPTH_COMPONENT; - } else if (desc.format == TEXTURE_FORMAT_8_8_8_8_RGBA_UNORM) { - internal_format = GL_RGBA; - } else { - internal_format = GL_RGB; - } - - GLint format = internal_format; - // FIXME: GLint format = desc.format == TEXTURE_FORMAT_DEPTH_DEFAULT ? GL_DEPTH_COMPONENT : - // GL_RGBA; - GLenum data_type = desc.format == TEXTURE_FORMAT_DEPTH_DEFAULT ? GL_FLOAT : GL_UNSIGNED_BYTE; - - if (desc.format == TEXTURE_FORMAT_DEPTH_DEFAULT) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - } else { - // set the texture wrapping parameters - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - // set texture filtering parameters - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - - if (data) { - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.extents.x, desc.extents.y, 0, format, - data_type, data); - if (desc.tex_type == TEXTURE_TYPE_2D) { - glGenerateMipmap(GL_TEXTURE_2D); - } - } else { - WARN("No image data provided"); - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.extents.x, desc.extents.y, 0, format, - data_type, NULL); - } - - glBindTexture(GL_TEXTURE_2D, 0); - - return handle; -} - -GPU_Texture* GPU_TextureAlloc(TextureHandle* out_handle) { - TextureHandle handle; - GPU_Texture* texture = Texture_pool_alloc(&context.resource_pools->textures, &handle); - DEBUG("Allocated texture with handle %d", handle.raw); - - GLuint gl_texture_id; - glGenTextures(1, &gl_texture_id); - texture->id = gl_texture_id; - - if (out_handle != NULL) { - *out_handle = handle; - } - - return texture; -} - -void GPU_TextureDestroy(TextureHandle handle) { glDeleteTextures(1, &handle.raw); } - -// TODO: void GPU_TextureUpload(TextureHandle handle, size_t n_bytes, const void* data) - -void GPU_EncodeBindPipeline(GPU_CmdEncoder* encoder, GPU_Pipeline* pipeline) { - encoder->pipeline = pipeline; - - // In OpenGL binding a pipeline is more or less equivalent to just setting the shader - glUseProgram(pipeline->shader_id); - - if (pipeline->wireframe) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - } else { - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } -} - -void GPU_EncodeBindShaderData(GPU_CmdEncoder* encoder, u32 group, ShaderDataLayout layout) { - for (u32 binding_i = 0; binding_i < layout.binding_count; binding_i++) { - ShaderBinding binding = layout.bindings[binding_i]; - - switch (binding.kind) { - case BINDING_BYTES: { -#ifdef RAL_ASSERTS - CASSERT_MSG(binding.data.bytes.data, "void* data pointer should be non null"); - CASSERT_MSG(binding.data.bytes.size > 0, "size should be greater than 0 bytes"); -#endif - BufferHandle b; - GPU_Buffer* ubo_buf; - bool found = false; - for (u32 i = 0; i < encoder->pipeline->uniform_count; i++) { - b = encoder->pipeline->uniform_bindings[i]; - ubo_buf = BUFFER_GET(b); - assert(ubo_buf->name != NULL); - if (strcmp(ubo_buf->name, binding.label) == 0) { - found = true; - break; - } - } - if (!found) { - ERROR("Couldnt find uniform buffer object for %s!!", binding.label); - break; - } - - i32 blockIndex = glGetUniformBlockIndex(encoder->pipeline->shader_id, binding.label); - if (blockIndex < 0) { - WARN("Couldn't retrieve block index for uniform block '%s'", binding.label); - break; - } - - glBindBuffer(GL_UNIFORM_BUFFER, ubo_buf->id.ubo); - glBufferSubData(GL_UNIFORM_BUFFER, 0, ubo_buf->size, binding.data.bytes.data); - break; - } - case BINDING_TEXTURE: { - GPU_Texture* tex = TEXTURE_GET(binding.data.texture.handle); - GLint tex_slot = glGetUniformLocation(encoder->pipeline->shader_id, binding.label); - if (tex_slot == GL_INVALID_VALUE || tex_slot < 0) { - WARN("Invalid binding label for texture %s - couldn't fetch texture slot uniform", - binding.label); - } - glUniform1i(tex_slot, binding_i); - glActiveTexture(GL_TEXTURE0 + binding_i); - glBindTexture(opengl_tex_type(tex->type), tex->id); - break; - } - default: - WARN("Unsupported binding kind"); - } - } -} - -void GPU_EncodeSetDefaults(GPU_CmdEncoder* encoder) {} - -void GPU_EncodeSetVertexBuffer(GPU_CmdEncoder* encoder, BufferHandle buf) { - GPU_Buffer* buffer = BUFFER_GET(buf); - if (buffer->vao == 0) { // if no VAO for this vertex buffer, create it - INFO("Setting up VAO"); - buffer->vao = opengl_bindcreate_vao(buffer, encoder->pipeline->vertex_desc); - } - glBindVertexArray(buffer->vao); -} -void GPU_EncodeSetIndexBuffer(GPU_CmdEncoder* encoder, BufferHandle buf) { - GPU_Buffer* buffer = BUFFER_GET(buf); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->id.ibo); -} -void GPU_EncodeDrawTris(GPU_CmdEncoder* encoder, u64 count) { - glDrawArrays(GL_TRIANGLES, 0, count); -} -void GPU_EncodeDrawIndexedTris(GPU_CmdEncoder* encoder, u64 index_count) { - glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_INT, 0); -} - -PUB void GPU_EncodeDraw(GPU_CmdEncoder* encoder, PrimitiveTopology topology, u64 count) { - glDrawArrays(opengl_prim_topology(topology), 0, count); -} -PUB void GPU_EncodeDrawIndexed(GPU_CmdEncoder* encoder, PrimitiveTopology topology, - u64 index_count) { - glDrawElements(opengl_prim_topology(topology), index_count, GL_UNSIGNED_INT, 0); -} - -PUB void GPU_WriteTextureRegion(GPU_CmdEncoder* encoder, TextureHandle dst, u32 x_offset, - u32 y_offset, u32 width, u32 height, const void* data) { - CASSERT_MSG(data, "const void* data must not be NULL"); - - GPU_Texture* tex = TEXTURE_GET(dst); - - glBindTexture(GL_TEXTURE_2D, tex->id); - glTexSubImage2D(GL_TEXTURE_2D, 0, x_offset, y_offset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, - data); -} - -bool GPU_Backend_BeginFrame() { - glViewport(0, 0, context.swapchain.dimensions.x * 2, context.swapchain.dimensions.y * 2); - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - return true; -} - -void GPU_Backend_EndFrame() { glfwSwapBuffers(context.window); } - -#endif diff --git a/src/ral/backends/opengl/backend_opengl.h b/src/ral/backends/opengl/backend_opengl.h deleted file mode 100644 index 7bd1b81..0000000 --- a/src/ral/backends/opengl/backend_opengl.h +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once -#include "defines.h" - -#if defined(CEL_REND_BACKEND_OPENGL) - -#include "maths_types.h" -#include "ral_impl.h" -#include "ral_types.h" - -#define MAX_PIPELINE_UNIFORM_BUFFERS 32 - -#define OPENGL_DEFAULT_FRAMEBUFFER 0 - -typedef struct GPU_Swapchain { - u32x2 dimensions; -} GPU_Swapchain; - -typedef struct GPU_Device { - u32 pad; -} GPU_Device; - -typedef struct GPU_PipelineLayout { - void* pad; -} GPU_PipelineLayout; - -typedef struct GPU_Pipeline { - u32 shader_id; - GPU_Renderpass* renderpass; - VertexDescription vertex_desc; - BufferHandle uniform_bindings[MAX_PIPELINE_UNIFORM_BUFFERS]; - u32 uniform_count; - bool wireframe; -} GPU_Pipeline; - -typedef struct GPU_Renderpass { - u32 fbo; - GPU_RenderpassDesc description; -} GPU_Renderpass; - -typedef struct GPU_CmdEncoder { - GPU_Pipeline* pipeline; -} GPU_CmdEncoder; // Recording - -typedef struct GPU_CmdBuffer { - void* pad; -} GPU_CmdBuffer; // Ready for submission - -typedef struct GPU_Buffer { - union { - u32 vbo; - u32 ibo; - u32 ubo; - } id; - union { - u32 vao; - u32 ubo_binding_point; - }; // Optional - char* name; - u64 size; -} GPU_Buffer; - -typedef struct GPU_Texture { - u32 id; - GPU_TextureType type; -} GPU_Texture; - -typedef struct opengl_support { - u32 pad; -} opengl_support; - -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); - -typedef enum GlCommandType { - GLCMD_DRAW, - GLCMD_DRAW_INDEXED, - GLCMD_BIND_VBUF, - GLCMD_BIND_IBUF, - GLCMD_SET_PROGRAM, -} GlCommandType; - -typedef struct GlCommand { - GlCommandType cmd_type; - union { - struct { - PrimitiveTopology topology; - u32 start_vertex; - u32 vertex_count; - // TODO: instance - } draw; - struct { - PrimitiveTopology topology; - u32 index_count; - } draw_indexed; - struct { - u32 buffer_id; - } bind_vbuf; - struct { - u32 buffer_id; - } bind_ibuf; - struct { - u32 program_id; - } set_program; - } data; -} GlCommand; - -#endif diff --git a/src/ral/backends/opengl/opengl_helpers.h b/src/ral/backends/opengl/opengl_helpers.h deleted file mode 100644 index 706e2a0..0000000 --- a/src/ral/backends/opengl/opengl_helpers.h +++ /dev/null @@ -1,159 +0,0 @@ -#pragma once -#include "defines.h" -#include "ral_common.h" -#include "ral_impl.h" -#if defined(CEL_REND_BACKEND_OPENGL) -#include "backend_opengl.h" -#include "file.h" -#include "log.h" -#include "ral_types.h" - -#include <glad/glad.h> -#include <glfw3.h> -#include "ral_types.h" - -typedef struct opengl_vertex_attr { - u32 count; - GLenum data_type; -} opengl_vertex_attr; - -static opengl_vertex_attr format_from_vertex_attr(VertexAttribType attr) { - switch (attr) { - case ATTR_F32: - return (opengl_vertex_attr){ .count = 1, .data_type = GL_FLOAT }; - case ATTR_U32: - return (opengl_vertex_attr){ .count = 1, .data_type = GL_UNSIGNED_INT }; - case ATTR_I32: - return (opengl_vertex_attr){ .count = 1, .data_type = GL_INT }; - case ATTR_F32x2: - return (opengl_vertex_attr){ .count = 2, .data_type = GL_FLOAT }; - case ATTR_U32x2: - // return VK_FORMAT_R32G32_UINT; - case ATTR_I32x2: - // return VK_FORMAT_R32G32_UINT; - case ATTR_F32x3: - return (opengl_vertex_attr){ .count = 3, .data_type = GL_FLOAT }; - case ATTR_U32x3: - // return VK_FORMAT_R32G32B32_UINT; - case ATTR_I32x3: - // return VK_FORMAT_R32G32B32_SINT; - case ATTR_F32x4: - return (opengl_vertex_attr){ .count = 4, .data_type = GL_FLOAT }; - case ATTR_U32x4: - // return VK_FORMAT_R32G32B32A32_UINT; - case ATTR_I32x4: - return (opengl_vertex_attr){ .count = 4, .data_type = GL_INT }; - } -} - -static u32 opengl_bindcreate_vao(GPU_Buffer* buf, VertexDescription desc) { - DEBUG("Vertex format name %s", desc.debug_label); - // 1. Bind the buffer - glBindBuffer(GL_ARRAY_BUFFER, buf->id.vbo); - // 2. Create new VAO - u32 vao; - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - - // Attributes - u32 attr_count = desc.attributes_count; - // printf("N attributes %d\n", attr_count); - u64 offset = 0; - size_t vertex_size = desc.use_full_vertex_size ? sizeof(Vertex) : VertexDesc_CalcStride(&desc); - for (u32 i = 0; i < desc.attributes_count; i++) { - opengl_vertex_attr format = format_from_vertex_attr(desc.attributes[i]); - glVertexAttribPointer(i, format.count, format.data_type, GL_FALSE, vertex_size, (void*)offset); - TRACE(" %d %d %d %d %d %s", i, format.count, format.data_type, vertex_size, offset, - desc.attr_names[i]); - glEnableVertexAttribArray(i); // nth index - size_t this_offset = VertexAttribSize(desc.attributes[i]); - // printf("offset total %lld this attr %zu\n", offset, this_offset); - offset += this_offset; - } - glBindBuffer(GL_ARRAY_BUFFER, 0); - - return vao; -} - -static u32 shader_create_separate(const char* vert_shader, const char* frag_shader) { - INFO("Load shaders at %s and %s", vert_shader, frag_shader); - int success; - char info_log[512]; - - u32 vertex = glCreateShader(GL_VERTEX_SHADER); - const char* vertex_shader_src = string_from_file(vert_shader); - if (vertex_shader_src == NULL) { - ERROR("EXIT: couldnt load shader"); - exit(-1); - } - glShaderSource(vertex, 1, &vertex_shader_src, NULL); - glCompileShader(vertex); - glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); - if (!success) { - glGetShaderInfoLog(vertex, 512, NULL, info_log); - printf("%s\n", info_log); - ERROR("EXIT: vertex shader compilation failed"); - exit(-1); - } - - // fragment shader - u32 fragment = glCreateShader(GL_FRAGMENT_SHADER); - const char* fragment_shader_src = string_from_file(frag_shader); - if (fragment_shader_src == NULL) { - ERROR("EXIT: couldnt load shader"); - exit(-1); - } - glShaderSource(fragment, 1, &fragment_shader_src, NULL); - glCompileShader(fragment); - glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); - if (!success) { - glGetShaderInfoLog(fragment, 512, NULL, info_log); - printf("%s\n", info_log); - ERROR("EXIT: fragment shader compilation failed"); - exit(-1); - } - - u32 shader_prog; - shader_prog = glCreateProgram(); - - glAttachShader(shader_prog, vertex); - glAttachShader(shader_prog, fragment); - glLinkProgram(shader_prog); - glDeleteShader(vertex); - glDeleteShader(fragment); - free((char*)vertex_shader_src); - free((char*)fragment_shader_src); - - return shader_prog; -} - -static GLenum opengl_tex_type(GPU_TextureType tex_type) { - switch (tex_type) { - case TEXTURE_TYPE_2D: - return GL_TEXTURE_2D; - case TEXTURE_TYPE_CUBE_MAP: - return GL_TEXTURE_CUBE_MAP; - default: - return GL_TEXTURE_2D; - } -} - -static GLenum opengl_prim_topology(PrimitiveTopology t) { - switch (t) { - case CEL_POINT: - return GL_POINT; - case CEL_LINE: - return GL_LINES; - case CEL_LINE_STRIP: - return GL_LINE_STRIP; - case CEL_TRI: - return GL_TRIANGLES; - case CEL_TRI_STRIP: - return GL_TRIANGLE_STRIP; - case PRIMITIVE_TOPOLOGY_COUNT: - WARN("Invalid PrimitiveTopology value"); - break; - } -} - -#endif diff --git a/src/ral/backends/vulkan/backend_vulkan.c b/src/ral/backends/vulkan/backend_vulkan.c deleted file mode 100644 index e69de29..0000000 --- a/src/ral/backends/vulkan/backend_vulkan.c +++ /dev/null diff --git a/src/ral/backends/vulkan/backend_vulkan.h b/src/ral/backends/vulkan/backend_vulkan.h deleted file mode 100644 index f31bed2..0000000 --- a/src/ral/backends/vulkan/backend_vulkan.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#ifdef CEL_REND_BACKEND_VULKAN -#include "defines.h" -#include "maths_types.h" -#include "ral.h" -#include "ral_impl.h" -#include "ral_types.h" - -#include <vulkan/vk_platform.h> -#include <vulkan/vulkan.h> -#include <vulkan/vulkan_core.h> - -// Provide definitions for RAL structs - -struct GPU_Swapchain { - VkSwapchainKHR handle; -}; - -struct GPU_Device { - VkPhysicalDevice physical_device; - VkDevice logical_device; -}; - -struct GPU_PipelineLayout {}; -struct GPU_Pipeline {}; -struct GPU_Renderpass {}; -struct GPU_CmdEncoder {}; -struct GPU_CmdBuffer {}; -struct GPU_Buffer { - VkBuffer handle; - VkDeviceMemory memory; - u64 size; -}; -struct GPU_Texture { - VkImage handle; - VkDeviceMemory memory; - u64 size; - VkImageView view; - VkSampler sampler; - char* debug_label; -}; - -#endif diff --git a/src/ral/backends/vulkan/vulkan_glossary.md b/src/ral/backends/vulkan/vulkan_glossary.md deleted file mode 100644 index 4214f9d..0000000 --- a/src/ral/backends/vulkan/vulkan_glossary.md +++ /dev/null @@ -1,18 +0,0 @@ -# Vulkan Glossary - -*from https://vkguide.dev/docs/introduction/vulkan_execution/* - -- **VkInstance**: The Vulkan context, used to access drivers. -- **VkPhysicalDevice**: A GPU. Used to query physical GPU details, like features, capabilities, memory size, etc. -- **VkDevice**: The “logical” GPU context that you actually execute things on. -- **VkBuffer**: A chunk of GPU visible memory. -- **VkImage**: A texture you can write to and read from. -- **VkPipeline**: Holds the state of the gpu needed to draw. For example: shaders, rasterization options, depth settings. -- **VkRenderPass**: Holds information about the images you are rendering into. All drawing commands have to be done inside a renderpass. Only used in legacy vkguide. -- **VkFrameBuffer**: Holds the target images for a renderpass. Only used in legacy vkguide. -- **VkCommandBuffer**: Encodes GPU commands. All execution that is performed on the GPU itself (not in the driver) has to be encoded in a VkCommandBuffer. -- **VkQueue**: Execution “port” for commands. GPUs will have a set of queues with different properties. Some allow only graphics commands, others only allow memory commands, etc. Command buffers are executed by submitting them into a queue, which will copy the rendering commands onto the GPU for execution. -- **VkDescriptorSet**: Holds the binding information that connects shader inputs to data such as VkBuffer resources and VkImage textures. Think of it as a set of gpu-side pointers that you bind once. -- **VkSwapchainKHR**: Holds the images for the screen. It allows you to render things into a visible window. The KHR suffix shows that it comes from an extension, which in this case is VK_KHR_swapchain. -- **VkSemaphore**: Synchronizes GPU to GPU execution of commands. Used for syncing multiple command buffer submissions one after another. -- **VkFence**: Synchronizes GPU to CPU execution of commands. Used to know if a command buffer has finished being executed on the GPU. diff --git a/src/ral/backends/vulkan/vulkan_helpers.h b/src/ral/backends/vulkan/vulkan_helpers.h deleted file mode 100644 index 23666c6..0000000 --- a/src/ral/backends/vulkan/vulkan_helpers.h +++ /dev/null @@ -1,199 +0,0 @@ -#pragma once - -#include <assert.h> -#include <vulkan/vulkan.h> -#include <vulkan/vulkan_core.h> - -#include "darray.h" -#include "defines.h" -#include "log.h" -#include "str.h" - -#define VULKAN_PHYS_DEVICE_MAX_EXTENSION_NAMES 36 - -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) \ - 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; - -typedef struct vulkan_physical_device_requirements { - bool graphics; - bool present; - bool compute; - bool transfer; - str8 device_ext_names[VULKAN_PHYS_DEVICE_MAX_EXTENSION_NAMES]; - size_t device_ext_name_count; - bool sampler_anistropy; - bool discrete_gpu; -} vulkan_physical_device_requirements; - -#define VULKAN_MAX_DEFAULT 32 - -typedef struct vulkan_swapchain_support_info { - VkSurfaceCapabilitiesKHR capabilities; - VkSurfaceFormatKHR formats[VULKAN_MAX_DEFAULT]; - u32 format_count; - VkPresentModeKHR present_modes[VULKAN_MAX_DEFAULT]; - u32 mode_count; -} vulkan_swapchain_support_info; - -VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback( - VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT flags, - const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data); - -static void vulkan_device_query_swapchain_support(VkPhysicalDevice device, VkSurfaceKHR surface, - vulkan_swapchain_support_info* out_support_info) { - // TODO: add VK_CHECK to these calls! - - // Surface capabilities - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &out_support_info->capabilities); - - // Surface formats - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &out_support_info->format_count, - 0); // Get number of formats - if (out_support_info->format_count > 0) { - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &out_support_info->format_count, - out_support_info->formats); - } - - // Present Modes - vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &out_support_info->mode_count, - 0); // Get number of formats - if (out_support_info->mode_count > 0) { - vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &out_support_info->mode_count, - out_support_info->present_modes); - } -} - -static VkSurfaceFormatKHR choose_swapchain_format( - vulkan_swapchain_support_info* swapchain_support) { - assert(swapchain_support->format_count > 0); - // find a format - for (u32 i = 0; i < swapchain_support->format_count; i++) { - VkSurfaceFormatKHR format = swapchain_support->formats[i]; - if (format.format == VK_FORMAT_B8G8R8A8_SRGB && - format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - return format; - } - } - return swapchain_support->formats[0]; -} - -// static bool physical_device_meets_requirements( -// VkPhysicalDevice device, VkSurfaceKHR surface, const VkPhysicalDeviceProperties* properties, -// const VkPhysicalDeviceFeatures* features, -// const vulkan_physical_device_requirements* requirements, -// vulkan_physical_device_queue_family_info* out_queue_info, -// vulkan_swapchain_support_info* out_swapchain_support) { -// // TODO: pass in an arena - -// out_queue_info->graphics_family_index = -1; -// out_queue_info->present_family_index = -1; -// out_queue_info->compute_family_index = -1; -// out_queue_info->transfer_family_index = -1; - -// if (requirements->discrete_gpu) { -// if (properties->deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { -// TRACE("Device is not a physical GPU. Skipping."); -// return false; -// } -// } - -// u32 queue_family_count = 0; -// vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, 0); -// VkQueueFamilyProperties queue_families[queue_family_count]; -// vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, queue_families); - -// INFO("Graphics | Present | Compute | Transfer | Name"); -// u8 min_transfer_score = 255; -// for (u32 i = 0; i < queue_family_count; i++) { -// u8 current_transfer_score = 0; - -// // Graphics queue -// if (queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { -// out_queue_info->graphics_family_index = i; -// current_transfer_score++; -// } - -// // Compute queue -// if (queue_families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) { -// out_queue_info->compute_family_index = i; -// current_transfer_score++; -// } - -// // Transfer queue -// if (queue_families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) { -// // always take the lowest score transfer index -// if (current_transfer_score <= min_transfer_score) { -// min_transfer_score = current_transfer_score; -// out_queue_info->transfer_family_index = i; -// } -// } - -// // Present Queue -// VkBool32 supports_present = VK_FALSE; -// vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &supports_present); -// if (supports_present) { -// out_queue_info->present_family_index = i; -// } -// } - -// INFO(" %d | %d | %d | %d | %s", -// out_queue_info->graphics_family_index != -1, out_queue_info->present_family_index != -1, -// out_queue_info->compute_family_index != -1, out_queue_info->transfer_family_index != -1, -// properties->deviceName); -// TRACE("Graphics Family queue index: %d", out_queue_info->graphics_family_index); -// TRACE("Present Family queue index: %d", out_queue_info->present_family_index); -// TRACE("Compute Family queue index: %d", out_queue_info->compute_family_index); -// TRACE("Transfer Family queue index: %d", out_queue_info->transfer_family_index); - -// if ((!requirements->graphics || -// (requirements->graphics && out_queue_info->graphics_family_index != -1))) { -// INFO("Physical device meets our requirements! Proceed."); - -// vulkan_device_query_swapchain_support( -// device, surface, out_swapchain_support - -// // TODO: error handling i.e. format count = 0 or present mode = 0 - -// ); -// return true; -// } - -// 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/ral/ral.h b/src/ral/ral.h deleted file mode 100644 index fdbadd3..0000000 --- a/src/ral/ral.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "ral_common.h" -#include "ral_impl.h" -#include "ral_types.h"
\ No newline at end of file diff --git a/src/ral/ral_common.c b/src/ral/ral_common.c deleted file mode 100644 index d921ac4..0000000 --- a/src/ral/ral_common.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "ral_common.h" -#include "ral_impl.h" - -void BackendPools_Init(arena* a, GPU_BackendPools* backend_pools) { - PipelineLayout_pool pipeline_layout_pool = - PipelineLayout_pool_create(a, MAX_PIPELINES, sizeof(GPU_PipelineLayout)); - backend_pools->pipeline_layouts = pipeline_layout_pool; - Pipeline_pool pipeline_pool = Pipeline_pool_create(a, MAX_PIPELINES, sizeof(GPU_Pipeline)); - backend_pools->pipelines = pipeline_pool; - Renderpass_pool rpass_pool = Renderpass_pool_create(a, MAX_RENDERPASSES, sizeof(GPU_Renderpass)); - backend_pools->renderpasses = rpass_pool; -} - -void ResourcePools_Init(arena* a, struct ResourcePools* res_pools) { - Buffer_pool buf_pool = Buffer_pool_create(a, MAX_BUFFERS, sizeof(GPU_Buffer)); - res_pools->buffers = buf_pool; - Texture_pool tex_pool = Texture_pool_create(a, MAX_TEXTURES, sizeof(GPU_Texture)); - res_pools->textures = tex_pool; -} - -VertexDescription static_3d_vertex_description() { - VertexDescription builder = { .debug_label = "Standard static 3d vertex format" }; - VertexDesc_AddAttr(&builder, "inPosition", ATTR_F32x3); - VertexDesc_AddAttr(&builder, "inNormal", ATTR_F32x3); - VertexDesc_AddAttr(&builder, "inTexCoords", ATTR_F32x2); - builder.use_full_vertex_size = true; - return builder; -} - -void VertexDesc_AddAttr(VertexDescription* builder, const char* name, VertexAttribType type) { - u32 i = builder->attributes_count; - - size_t size = VertexAttribSize(type); - builder->attributes[i] = type; - // builder->stride += size; - builder->attr_names[i] = name; - - builder->attributes_count++; -} - -size_t VertexAttribSize(VertexAttribType attr) { - switch (attr) { - case ATTR_F32: - case ATTR_U32: - case ATTR_I32: - return 4; - case ATTR_F32x2: - case ATTR_U32x2: - case ATTR_I32x2: - return 8; - case ATTR_F32x3: - case ATTR_U32x3: - case ATTR_I32x3: - return 12; - case ATTR_F32x4: - case ATTR_U32x4: - case ATTR_I32x4: - return 16; - break; - } -} - -size_t VertexDesc_CalcStride(VertexDescription* desc) { - size_t stride = 0; - for (int i = 0; i < desc->attributes_count; i++) { - size_t size = VertexAttribSize(desc->attributes[i]); - stride += size; - } - return stride; -} diff --git a/src/ral/ral_common.h b/src/ral/ral_common.h deleted file mode 100644 index 5a797e5..0000000 --- a/src/ral/ral_common.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @brief Common functions that don't actually depend on the specific backend - */ -#pragma once -#include "buf.h" -#include "defines.h" -#include "mem.h" -#include "ral_types.h" -// #include "ral_impl.h" - -// Concrete implementation -#if defined(CEL_REND_BACKEND_OPENGL) -#include "backend_opengl.h" -#endif - -TYPED_POOL(GPU_Buffer, Buffer); -TYPED_POOL(GPU_Texture, Texture); -TYPED_POOL(GPU_PipelineLayout, PipelineLayout); -TYPED_POOL(GPU_Pipeline, Pipeline); -TYPED_POOL(GPU_Renderpass, Renderpass); - -// --- Handy macros -#define BUFFER_GET(h) (Buffer_pool_get(&context.resource_pools->buffers, h)) -#define TEXTURE_GET(h) (Texture_pool_get(&context.resource_pools->textures, h)) - -// --- Views -typedef struct GPU_BufferView { - BufferHandle buf; - size_t offset; - size_t bytes; -} GPU_BufferView; - -// --- Pools -typedef struct GPU_BackendPools { - Pipeline_pool pipelines; - PipelineLayout_pool pipeline_layouts; - Renderpass_pool renderpasses; -} GPU_BackendPools; -void BackendPools_Init(arena* a, GPU_BackendPools* backend_pools); - -struct ResourcePools { - Buffer_pool buffers; - Texture_pool textures; -}; -typedef struct ResourcePools ResourcePools; -void ResourcePools_Init(arena* a, struct ResourcePools* res_pools); - -PUB GPU_Renderpass* GPU_GetDefaultRenderpass(); // returns a renderpass that draws directly to - // default framebuffer with default depth - -// -- -// window resize callback -void GPU_WindowResizedCallback(u32 x, u32 y); - -// --- Vertex formats -VertexDescription static_3d_vertex_description(); - -void VertexDesc_AddAttr(VertexDescription* builder, const char* name, VertexAttribType type); -size_t VertexDesc_CalcStride(VertexDescription* desc); - -size_t VertexAttribSize(VertexAttribType attr); diff --git a/src/ral/ral_impl.h b/src/ral/ral_impl.h deleted file mode 100644 index 16c9767..0000000 --- a/src/ral/ral_impl.h +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @brief - */ -#pragma once -#include "buf.h" -#include "defines.h" -#include "ral_types.h" - -struct GLFWwindow; -struct ResourcePools; - -// Forward declare structs - these must be defined in the backend implementation -typedef struct GPU_Swapchain GPU_Swapchain; -typedef struct GPU_Device GPU_Device; -typedef struct GPU_PipelineLayout GPU_PipelineLayout; -typedef struct GPU_Pipeline GPU_Pipeline; -typedef struct GPU_Renderpass GPU_Renderpass; -typedef struct GPU_CmdEncoder GPU_CmdEncoder; // Recording -typedef struct GPU_CmdBuffer GPU_CmdBuffer; // Ready for submission -typedef struct GPU_Buffer GPU_Buffer; -typedef struct GPU_Texture GPU_Texture; - -bool GPU_Backend_Init(const char* window_name, struct GLFWwindow* window, - struct ResourcePools* res_pools); -void GPU_Backend_Shutdown(); - -bool GPU_Device_Create(GPU_Device* out_device); -void GPU_Device_Destroy(GPU_Device* device); - -bool GPU_Swapchain_Create(GPU_Swapchain* out_swapchain); -void GPU_Swapchain_Destroy(GPU_Swapchain* swapchain); -void GPU_Swapchain_Resize(i32 new_width, i32 new_height); -u32x2 GPU_Swapchain_GetDimensions(); - -PUB GPU_Renderpass* GPU_Renderpass_Create(GPU_RenderpassDesc description); -PUB void GPU_Renderpass_Destroy(GPU_Renderpass* pass); - -PUB GPU_Pipeline* GPU_GraphicsPipeline_Create(GraphicsPipelineDesc description, - GPU_Renderpass* renderpass); -PUB void GraphicsPipeline_Destroy(GPU_Pipeline* pipeline); - -// --- Command buffer -PUB GPU_CmdEncoder GPU_CmdEncoder_Create(); -PUB void GPU_CmdEncoder_Destroy(GPU_CmdEncoder* encoder); -PUB void GPU_CmdEncoder_Begin(GPU_CmdEncoder* encoder); -PUB void GPU_CmdEncoder_Finish(GPU_CmdEncoder* encoder); -PUB void GPU_CmdEncoder_BeginRender(GPU_CmdEncoder* encoder, GPU_Renderpass* renderpass); -PUB void GPU_CmdEncoder_EndRender(GPU_CmdEncoder* encoder); -PUB GPU_CmdEncoder* GPU_GetDefaultEncoder(); -PUB void GPU_QueueSubmit(GPU_CmdBuffer* cmd_buffer); - -// --- Buffers -PUB BufferHandle GPU_BufferCreate(u64 size, GPU_BufferType buf_type, GPU_BufferFlags flags, - const void* data); -PUB void GPU_BufferDestroy(BufferHandle handle); -PUB void GPU_BufferUpload(BufferHandle buffer, size_t n_bytes, const void* data); - -// --- Textures -PUB TextureHandle GPU_TextureCreate(TextureDesc desc, bool create_view, const void* data); -PUB GPU_Texture* GPU_TextureAlloc(TextureHandle* out_handle); -PUB void GPU_TextureDestroy(TextureHandle handle); -PUB void GPU_TextureUpload(TextureHandle handle, size_t n_bytes, const void* data); - -// --- Data copy commands -PUB void GPU_EncodeCopyBufToBuf(GPU_CmdEncoder* encoder, BufferHandle src, u64 src_offset, - BufferHandle dst, u64 dst_offset, u64 copy_size); - -// PUB void GPU_EncodeCopyBufToTex(GPU_CmdEncoder* encoder, BufferHandle src, TextureHandle dst, -// u32 x_offset, u32 y_offset, u32 width, u32 height, const void* data); -/** @brief Convenience method for writing data directly into a texture. Staging memory is handled - * internally. */ -PUB void GPU_WriteTextureRegion(GPU_CmdEncoder* encoder, TextureHandle dst, u32 x_offset, - u32 y_offset, u32 width, u32 height, const void* data); -PUB void GPU_WriteBuffer(GPU_CmdEncoder* encoder, BufferHandle buf, u64 offset, u64 size, - const void* data); - -// --- Render commands -PUB void GPU_EncodeBindPipeline(GPU_CmdEncoder* encoder, GPU_Pipeline* pipeline); -PUB void GPU_EncodeBindShaderData(GPU_CmdEncoder* encoder, u32 group, ShaderDataLayout layout); -void GPU_EncodeSetDefaults(GPU_CmdEncoder* encoder); -PUB void GPU_EncodeSetVertexBuffer(GPU_CmdEncoder* encoder, BufferHandle buf); -PUB void GPU_EncodeSetIndexBuffer(GPU_CmdEncoder* encoder, BufferHandle buf); - -PUB void GPU_EncodeDraw(GPU_CmdEncoder* encoder, PrimitiveTopology topology, u64 count); -PUB void GPU_EncodeDrawIndexed(GPU_CmdEncoder* encoder, PrimitiveTopology topology, - u64 index_count); -// convenience versions of the above -PUB void GPU_EncodeDrawTris(GPU_CmdEncoder* encoder, u64 count); -PUB void GPU_EncodeDrawIndexedTris(GPU_CmdEncoder* encoder, u64 index_count); -PUB void GPU_EncodeDrawInstanced(GPU_CmdEncoder* encoder, u64 index_count, - u64 instance_count); // TODO: implement instanced rendering - -// --- Frame cycle -PUB bool GPU_Backend_BeginFrame(); -PUB void GPU_Backend_EndFrame(); - -// Concrete implementation -#if defined(CEL_REND_BACKEND_OPENGL) -#include "backend_opengl.h" -#elif defined(CEL_REND_BACKEND_VULKAN) -#include "backend_vulkan.h" -#endif diff --git a/src/ral/ral_types.h b/src/ral/ral_types.h deleted file mode 100644 index fde3bed..0000000 --- a/src/ral/ral_types.h +++ /dev/null @@ -1,168 +0,0 @@ -#pragma once -#include "darray.h" -#include "defines.h" -#include "maths_types.h" -#include "str.h" - -// --- Max size constants -#define MAX_SHADER_DATA_LAYOUTS 8 -#define MAX_SHADER_BINDINGS 8 -#define MAX_BUFFERS 256 -#define MAX_TEXTURES 256 -#define MAX_PIPELINES 128 -#define MAX_RENDERPASSES 128 -#define MAX_VERTEX_ATTRIBUTES 16 - -// --- Handle types -CORE_DEFINE_HANDLE(BufferHandle); -CORE_DEFINE_HANDLE(TextureHandle); -CORE_DEFINE_HANDLE(SamplerHandle); -CORE_DEFINE_HANDLE(ShaderHandle); -CORE_DEFINE_HANDLE(PipelineLayoutHandle); -CORE_DEFINE_HANDLE(PipelineHandle); -CORE_DEFINE_HANDLE(RenderpassHandle); -#define INVALID_TEX_HANDLE ((TextureHandle){ .raw = 9999981 }) - -// --- Buffers -typedef enum GPU_BufferType { - BUFFER_DEFAULT, // on Vulkan this would be a storage buffer? - BUFFER_VERTEX, - BUFFER_INDEX, - BUFFER_UNIFORM, - BUFFER_COUNT -} GPU_BufferType; - -static const char* buffer_type_names[] = { - "RAL Buffer Default", "RAL Buffer Vertex", "RAL Buffer Index", - "RAL Buffer Uniform", "RAL Buffer Count", -}; - -typedef enum GPU_BufferFlag { - BUFFER_FLAG_CPU = 1 << 0, - BUFFER_FLAG_GPU = 1 << 1, - BUFFER_FLAG_STORAGE = 1 << 2, - BUFFER_FLAG_COUNT -} GPU_BufferFlag; -typedef u32 GPU_BufferFlags; - -static const char* texture_type_names[] = { - "RAL Texture 2D", "RAL Texture 3D", "RAL Texture 2D Array", - "RAL Texture Cubemap", "RAL Texture Count", -}; - -typedef enum GPU_TextureFormat { - TEXTURE_FORMAT_8_8_8_8_RGBA_UNORM, - TEXTURE_FORMAT_8_8_8_RGB_UNORM, - TEXTURE_FORMAT_DEPTH_DEFAULT, - TEXTURE_FORMAT_COUNT -} GPU_TextureFormat; - -// --- Vertices - -typedef enum VertexFormat { - VERTEX_STATIC_3D, - VERTEX_SPRITE, - VERTEX_SKINNED, - VERTEX_COLOURED_STATIC_3D, - VERTEX_RAW_POS_COLOUR, - VERTEX_POS_ONLY, - VERTEX_COUNT -} VertexFormat; - -#ifndef TYPED_VERTEX_ARRAY -KITC_DECL_TYPED_ARRAY(Vertex); -KITC_DECL_TYPED_ARRAY(u32) -#define TYPED_VERTEX_ARRAY -#endif - -/// @strip_prefix(ATTR_) -typedef enum VertexAttribType { - ATTR_F32, - ATTR_F32x2, - ATTR_F32x3, - ATTR_F32x4, - ATTR_U32, - ATTR_U32x2, - ATTR_U32x3, - ATTR_U32x4, - ATTR_I32, - ATTR_I32x2, - ATTR_I32x3, - ATTR_I32x4, -} VertexAttribType; - -typedef struct VertexDescription { - const char* debug_label; - const char* attr_names[MAX_VERTEX_ATTRIBUTES]; - VertexAttribType attributes[MAX_VERTEX_ATTRIBUTES]; - u32 attributes_count; - // size_t stride; - bool use_full_vertex_size; -} VertexDescription; - -// --- Shaders -typedef enum PipelineKind { - PIPELINE_GRAPHICS, - PIPELINE_COMPUTE, -} PipelineKind; - -typedef struct ShaderDesc { - const char* debug_name; - Str8 filepath; // Where it came from - Str8 code; // Either GLSL or SPIRV bytecode - bool is_spirv; - bool is_combined_vert_frag; // Contains both vertex and fragment stages -} ShaderDesc; - -typedef ShaderDataLayout (*FN_GetBindingLayout)(void* data); - -/** @brief takes a `ShaderDataLayout` without data, and puts the correct data into each binding */ -typedef void (*FN_BindShaderData)(ShaderDataLayout* layout, const void* data); - -// typedef struct ShaderData { -// FN_GetBindingLayout get_layout; -// void* data; -// } ShaderData; - -typedef enum PrimitiveTopology { -#ifdef TOPOLOGY_SHORT_NAMES - CEL_POINT, - CEL_LINE, - CEL_LINE_STRIP, - CEL_TRI, - CEL_TRI_STRIP, - PRIMITIVE_TOPOLOGY_COUNT -#else - PRIMITIVE_TOPOLOGY_POINT, - PRIMITIVE_TOPOLOGY_LINE, - PRIMITIVE_TOPOLOGY_LINE_STRIP, - PRIMITIVE_TOPOLOGY_TRIANGLE, - PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, - PRIMITIVE_TOPOLOGY_COUNT -#endif -} PrimitiveTopology; - -typedef enum Winding { WINDING_CCW, WINDING_CW } Winding; - -// based on https://registry.khronos.org/OpenGL-Refpages/gl4/html/glDepthFunc.xhtml -typedef enum CompareFunc { - COMPARE_NEVER, - COMPARE_LESS, - COMPARE_EQUAL, - COMPARE_LESS_EQUAL, - COMPARE_GREATER, - COMPARE_NOT_EQUAL, - COMPARE_GREATER_EQUAL, - COMPARE_ALWAYS, - COMPARE_COUNT -} CompareFunc; - -bool GraphicsPipelineDesc_AddShaderDataLayout(GraphicsPipelineDesc* desc, ShaderDataLayout layout); - -typedef struct GPU_RenderpassDesc { - bool default_framebuffer; - bool has_color_target; - TextureHandle color_target; // for now only support one - bool has_depth_stencil; - TextureHandle depth_stencil; -} GPU_RenderpassDesc; diff --git a/src/render/archive/backends/backend_test.c b/src/render/archive/backends/backend_test.c deleted file mode 100644 index 6347e27..0000000 --- a/src/render/archive/backends/backend_test.c +++ /dev/null @@ -1 +0,0 @@ -// #FUTURE
\ No newline at end of file diff --git a/src/render/archive/backends/metal/README.md b/src/render/archive/backends/metal/README.md deleted file mode 100644 index f87f5c1..0000000 --- a/src/render/archive/backends/metal/README.md +++ /dev/null @@ -1 +0,0 @@ -# TODO
\ No newline at end of file diff --git a/src/render/archive/backends/metal/backend_metal.h b/src/render/archive/backends/metal/backend_metal.h deleted file mode 100644 index 9561bb6..0000000 --- a/src/render/archive/backends/metal/backend_metal.h +++ /dev/null @@ -1,74 +0,0 @@ -#pragma once -// #define CEL_REND_BACKEND_METAL -#if defined(CEL_REND_BACKEND_METAL) - -#include "defines.h" -#include "maths_types.h" -#ifdef __OBJC__ -#import <Foundation/Foundation.h> -#import <Metal/Metal.h> -#import <MetalKit/MetalKit.h> -#import <QuartzCore/CAMetalLayer.h> -#else -typedef void* id; -#endif - -typedef struct gpu_swapchain { - u32x2 dimensions; -#ifdef __OBJC__ - CAMetalLayer* swapchain; -#else - void* swapchain; -#endif -} gpu_swapchain; -typedef struct gpu_device { -/** @brief `device` gives us access to our GPU */ -#ifdef __OBJC__ - id<MTLDevice> id; -#else - void* id; -#endif -} gpu_device; -typedef struct gpu_pipeline_layout { - void* pad; -} gpu_pipeline_layout; -typedef struct gpu_pipeline { -#ifdef __OBJC__ - id<MTLRenderPipelineState> pipeline_state; -#else - void* pipeline_state; -#endif -} gpu_pipeline; -typedef struct gpu_renderpass { -#ifdef __OBJC__ - MTLRenderPassDescriptor* rpass_descriptor; -#else - void* rpass_descriptor; -#endif -} gpu_renderpass; -typedef struct gpu_cmd_encoder { -#ifdef __OBJC__ - id<MTLCommandBuffer> cmd_buffer; - id<MTLRenderCommandEncoder> render_encoder; -#else - void* cmd_buffer; - void* render_encoder; -#endif -} gpu_cmd_encoder; -typedef struct gpu_cmd_buffer { - void* pad; -} gpu_cmd_buffer; - -typedef struct gpu_buffer { -#ifdef __OBJC__ - id<MTLBuffer> id; -#else - void* id; -#endif - u64 size; -} gpu_buffer; -typedef struct gpu_texture { - void* pad; -} gpu_texture; - -#endif
\ No newline at end of file diff --git a/src/render/archive/backends/metal/backend_metal.m b/src/render/archive/backends/metal/backend_metal.m deleted file mode 100644 index 4787755..0000000 --- a/src/render/archive/backends/metal/backend_metal.m +++ /dev/null @@ -1,285 +0,0 @@ -#include <assert.h> -// #define CEL_REND_BACKEND_METAL -#if defined(CEL_REND_BACKEND_METAL) -#include <stddef.h> -#include "ral_types.h" -#include "colours.h" -#include <stdlib.h> -#include "camera.h" -#include "defines.h" -#include "file.h" -#include "log.h" -#include "maths_types.h" -#include "ral.h" - -#define GLFW_INCLUDE_NONE -#define GLFW_EXPOSE_NATIVE_COCOA - -#include <GLFW/glfw3.h> -#include <GLFW/glfw3native.h> - -#import <Foundation/Foundation.h> -#import <Metal/Metal.h> -#import <MetalKit/MetalKit.h> -#import <QuartzCore/CAMetalLayer.h> -#include "backend_metal.h" - -// --- Handy macros -#define BUFFER_GET(h) (buffer_pool_get(&context.resource_pools->buffers, h)) -#define TEXTURE_GET(h) (texture_pool_get(&context.resource_pools->textures, h)) - -typedef struct metal_context { - GLFWwindow* window; - NSWindow* metal_window; - arena pool_arena; - - gpu_device* device; - gpu_swapchain* swapchain; - id<CAMetalDrawable> surface; - - id<MTLCommandQueue> command_queue; - gpu_cmd_encoder main_command_buf; - gpu_backend_pools gpu_pools; - struct resource_pools* resource_pools; -} metal_context; - -static metal_context context; - -struct GLFWwindow; - -bool gpu_backend_init(const char *window_name, struct GLFWwindow *window) { - INFO("loading Metal backend"); - - memset(&context, 0, sizeof(metal_context)); - context.window = window; - - size_t pool_buffer_size = 1024 * 1024; - context.pool_arena = arena_create(malloc(pool_buffer_size), pool_buffer_size); - - backend_pools_init(&context.pool_arena, &context.gpu_pools); - context.resource_pools = malloc(sizeof(struct resource_pools)); - resource_pools_init(&context.pool_arena, context.resource_pools); - - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - - glfwMakeContextCurrent(window); - // FIXME: glfwSetFramebufferSizeCallback(ren->window, framebuffer_size_callback); - - // get a NSWindow pointer from GLFWwindow - NSWindow *nswindow = glfwGetCocoaWindow(window); - context.metal_window = nswindow; - - // const id<MTLCommandQueue> queue = [gpu newCommandQueue]; - // CAMetalLayer *swapchain = [CAMetalLayer layer]; - // swapchain.device = gpu; - // swapchain.opaque = YES; - - // // set swapchain for the window - // nswindow.contentView.layer = swapchain; - // nswindow.contentView.wantsLayer = YES; - - // MTLClearColor color = MTLClearColorMake(0.7, 0.1, 0.2, 1.0); - - // // set all our state properties - // state->device = gpu; - // state->cmd_queue = queue; - // state->swapchain = swapchain; - // state->clear_color = color; - - // NSError *err = 0x0; // TEMPORARY - - // WARN("About to try loading metallib"); - // id<MTLLibrary> defaultLibrary = [state->device newLibraryWithFile: @"build/gfx.metallib" error:&err]; - // CASSERT(defaultLibrary); - // state->default_lib = defaultLibrary; - // if (!state->default_lib) { - // NSLog(@"Failed to load library"); - // exit(0); - // } - - // create_render_pipeline(state); - - return true; -} - -void gpu_backend_shutdown() {} - -bool gpu_device_create(gpu_device* out_device) { - TRACE("GPU Device creation"); - const id<MTLDevice> gpu = MTLCreateSystemDefaultDevice(); - out_device->id = gpu; - context.device = out_device; - - const id<MTLCommandQueue> queue = [gpu newCommandQueue]; - context.command_queue = queue; - - return true; -} -void gpu_device_destroy() {} - -// --- Render Pipeline -gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description) { - TRACE("GPU Graphics Pipeline creation"); - // Allocate - // gpu_pipeline_layout* layout = - // pipeline_layout_pool_alloc(&context.gpu_pools.pipeline_layouts, NULL); - gpu_pipeline* pipeline = pipeline_pool_alloc(&context.gpu_pools.pipelines, NULL); - - WARN("About to try loading metallib"); - assert(description.vs.is_combined_vert_frag); - // Ignore fragment shader data, as vert shader data contains both - NSError *err = 0x0; // TEMPORARY - NSString *myNSString = [NSString stringWithUTF8String:(char*)description.vs.filepath.buf]; - id<MTLLibrary> default_library = [context.device->id newLibraryWithFile:myNSString error:&err]; - assert(default_library); - - // setup vertex and fragment shaders - id<MTLFunction> ren_vert = [default_library newFunctionWithName:@"basic_vertex"]; - assert(ren_vert); - id<MTLFunction> ren_frag = [default_library newFunctionWithName:@"basic_fragment"]; - assert(ren_frag); - - // create pipeline descriptor - @autoreleasepool { - NSError *err = 0x0; - MTLRenderPipelineDescriptor *pld = [[MTLRenderPipelineDescriptor alloc] init]; - NSString *pipeline_name = [NSString stringWithUTF8String: description.debug_name]; - pld.label = pipeline_name; - pld.vertexFunction = ren_vert; - pld.fragmentFunction = ren_frag; - pld.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; - pld.colorAttachments[0].blendingEnabled = YES; - - MTLDepthStencilDescriptor *depthStencilDescriptor = [MTLDepthStencilDescriptor new]; - depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionLess; - depthStencilDescriptor.depthWriteEnabled = YES; - pld.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; - - id<MTLDepthStencilState> depth_descriptor = [context.device->id newDepthStencilStateWithDescriptor:depthStencilDescriptor]; - // FIXME: state->depth_state = depth_descriptor; - - id<MTLRenderPipelineState> pipeline_state = [context.device->id newRenderPipelineStateWithDescriptor:pld error:&err]; - TRACE("created renderpipelinestate"); - pipeline->pipeline_state = pipeline_state; - - } - - return pipeline; -} -void gpu_pipeline_destroy(gpu_pipeline* pipeline) {} - -// --- Renderpass -gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description) { - gpu_renderpass* renderpass = renderpass_pool_alloc(&context.gpu_pools.renderpasses, NULL); - - // TODO: Configure based on description - // set up render pass - context.surface = [context.swapchain->swapchain nextDrawable]; - MTLRenderPassDescriptor *renderPassDescriptor = [[MTLRenderPassDescriptor alloc] init]; - MTLRenderPassColorAttachmentDescriptor *cd = renderPassDescriptor.colorAttachments[0]; - [cd setTexture:context.surface.texture]; - [cd setLoadAction:MTLLoadActionClear]; - MTLClearColor clearColor = MTLClearColorMake(0.1, 0.1, 0.0, 1.0); - [cd setClearColor:clearColor]; - [cd setStoreAction:MTLStoreActionStore]; - - renderpass->rpass_descriptor = renderPassDescriptor; - - return renderpass; -} - -void gpu_renderpass_destroy(gpu_renderpass* pass) {} - -// --- Swapchain -bool gpu_swapchain_create(gpu_swapchain* out_swapchain) { - TRACE("GPU Swapchain creation"); - CAMetalLayer *swapchain = [CAMetalLayer layer]; - swapchain.device = context.device->id; - swapchain.opaque = YES; - out_swapchain->swapchain = swapchain; - - // set swapchain for the window - context.metal_window.contentView.layer = swapchain; - context.metal_window.contentView.wantsLayer = YES; - - context.swapchain = out_swapchain; - return true; -} -void gpu_swapchain_destroy(gpu_swapchain* swapchain) {} - -// --- Command buffer -gpu_cmd_encoder gpu_cmd_encoder_create() { - id <MTLCommandBuffer> cmd_buffer = [context.command_queue commandBuffer]; - - return (gpu_cmd_encoder) { - .cmd_buffer = cmd_buffer - }; -} -void gpu_cmd_encoder_destroy(gpu_cmd_encoder* encoder) {} -void gpu_cmd_encoder_begin(gpu_cmd_encoder encoder) { /* no-op */ } -void gpu_cmd_encoder_begin_render(gpu_cmd_encoder* encoder, gpu_renderpass* renderpass) { - DEBUG("Create Render Command Encoder"); - id<MTLRenderCommandEncoder> render_encoder = [encoder->cmd_buffer renderCommandEncoderWithDescriptor:renderpass->rpass_descriptor]; - encoder->render_encoder = render_encoder; - // [encoder setDepthStencilState:state->depth_state]; -} -void gpu_cmd_encoder_end_render(gpu_cmd_encoder* encoder) {} -void gpu_cmd_encoder_begin_compute() {} -gpu_cmd_encoder* gpu_get_default_cmd_encoder() { - return &context.main_command_buf; -} - -/** @brief Finish recording and return a command buffer that can be submitted to a queue */ -gpu_cmd_buffer gpu_cmd_encoder_finish(gpu_cmd_encoder* encoder) {} - -void gpu_queue_submit(gpu_cmd_buffer* buffer) {} - -void encode_buffer_copy(gpu_cmd_encoder* encoder, buffer_handle src, u64 src_offset, - buffer_handle dst, u64 dst_offset, u64 copy_size); -void buffer_upload_bytes(buffer_handle gpu_buf, bytebuffer cpu_buf, u64 offset, u64 size); - -void copy_buffer_to_buffer_oneshot(buffer_handle src, u64 src_offset, buffer_handle dst, - u64 dst_offset, u64 copy_size); -void copy_buffer_to_image_oneshot(buffer_handle src, texture_handle dst); - -void encode_bind_pipeline(gpu_cmd_encoder* encoder, pipeline_kind kind, gpu_pipeline* pipeline) {} -void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* data) {} -void encode_set_default_settings(gpu_cmd_encoder* encoder) { - [encoder->render_encoder setCullMode:MTLCullModeBack]; -} -void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) { - gpu_buffer* vertex_buf = BUFFER_GET(buf); - [encoder->render_encoder setVertexBuffer:vertex_buf->id offset:0 atIndex:0]; -} -void encode_set_index_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) {} -void encode_set_bind_group() {} -void encode_draw(gpu_cmd_encoder* encoder) {} -void encode_draw_indexed(gpu_cmd_encoder* encoder, u64 index_count) {} -void encode_clear_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) {} - -buffer_handle gpu_buffer_create(u64 size, gpu_buffer_type buf_type, gpu_buffer_flags flags, - const void* data) { - buffer_handle handle; - gpu_buffer* buffer = buffer_pool_alloc(&context.resource_pools->buffers, &handle); - buffer->size = size; - - id<MTLBuffer> mtl_vert_buf = [context.device->id newBufferWithBytes:data - length: size - options:MTLResourceStorageModeShared]; - return handle; -} -void gpu_buffer_destroy(buffer_handle buffer) {} -void gpu_buffer_upload(const void* data) {} - -texture_handle gpu_texture_create(texture_desc desc, bool create_view, const void* data) {} -void gpu_texture_destroy(texture_handle) {} -void gpu_texture_upload(texture_handle texture, const void* data) {} - -bool gpu_backend_begin_frame() { - context.main_command_buf.cmd_buffer = [context.command_queue commandBuffer]; - return true; - } -void gpu_backend_end_frame() {} -void gpu_temp_draw(size_t n_verts) {} - -#endif
\ No newline at end of file diff --git a/src/render/archive/backends/opengl/backend_opengl.c b/src/render/archive/backends/opengl/backend_opengl.c deleted file mode 100644 index 43105e2..0000000 --- a/src/render/archive/backends/opengl/backend_opengl.c +++ /dev/null @@ -1,521 +0,0 @@ -#include <stddef.h> -#include <stdio.h> -#include <string.h> -#include "colours.h" -#include "maths.h" -#include "opengl_helpers.h" -#include "ral_types.h" -#define CEL_REND_BACKEND_OPENGL -#if defined(CEL_REND_BACKEND_OPENGL) -#include <assert.h> -#include <stdlib.h> - -#include "backend_opengl.h" -#include "defines.h" -#include "file.h" -#include "log.h" -#include "maths_types.h" -#include "ral.h" - -#include <glad/glad.h> -#include <glfw3.h> - -typedef struct opengl_context { - GLFWwindow* window; - arena pool_arena; - gpu_cmd_encoder command_buffer; - gpu_backend_pools gpu_pools; - struct resource_pools* resource_pools; -} opengl_context; - -static opengl_context context; - -struct GLFWwindow; - -bool gpu_backend_init(const char* window_name, struct GLFWwindow* window) { - INFO("loading OpenGL backend"); - - memset(&context, 0, sizeof(opengl_context)); - context.window = window; - - size_t pool_buffer_size = 1024 * 1024; - context.pool_arena = arena_create(malloc(pool_buffer_size), pool_buffer_size); - - backend_pools_init(&context.pool_arena, &context.gpu_pools); - context.resource_pools = malloc(sizeof(struct resource_pools)); - resource_pools_init(&context.pool_arena, context.resource_pools); - - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); - - // glad: load all opengl function pointers - if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { - ERROR("Failed to initialise GLAD \n"); - return false; - } - - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - - return true; -} - -// --- Render Pipeline -gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description) { - gpu_pipeline* pipeline = pipeline_pool_alloc(&context.gpu_pools.pipelines, NULL); - - // Create shader program - u32 shader_id = shader_create_separate(description.vs.filepath.buf, description.fs.filepath.buf); - pipeline->shader_id = shader_id; - - // Vertex format - pipeline->vertex_desc = description.vertex_desc; - - // Allocate uniform buffers if needed - u32 ubo_count = 0; - // printf("data layouts %d\n", description.data_layouts_count); - for (u32 layout_i = 0; layout_i < description.data_layouts_count; layout_i++) { - shader_data_layout sdl = description.data_layouts[layout_i].shader_data_get_layout(NULL); - TRACE("Got shader data layout %d's bindings! . found %d", layout_i, sdl.bindings_count); - - for (u32 binding_j = 0; binding_j < sdl.bindings_count; binding_j++) { - u32 binding_id = binding_j; - assert(binding_id < MAX_PIPELINE_UNIFORM_BUFFERS); - shader_binding binding = sdl.bindings[binding_j]; - if (binding.type == SHADER_BINDING_BYTES) { - static u32 s_binding_point = 0; - buffer_handle ubo_handle = - gpu_buffer_create(binding.data.bytes.size, CEL_BUFFER_UNIFORM, CEL_BUFFER_FLAG_GPU, - NULL); // no data right now - pipeline->uniform_bindings[ubo_count++] = ubo_handle; - gpu_buffer* ubo_buf = BUFFER_GET(ubo_handle); - - i32 blockIndex = glGetUniformBlockIndex(pipeline->shader_id, binding.label); - printf("Block index for %s: %d", binding.label, blockIndex); - if (blockIndex < 0) { - WARN("Couldn't retrieve block index for uniform block '%s'", binding.label); - } else { - // DEBUG("Retrived block index %d for %s", blockIndex, binding.label); - } - u32 blocksize; - glGetActiveUniformBlockiv(pipeline->shader_id, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, - &blocksize); - printf("\t with size %d bytes\n", blocksize); - - glBindBufferBase(GL_UNIFORM_BUFFER, s_binding_point, ubo_buf->id.ubo); - if (blockIndex != GL_INVALID_INDEX) { - glUniformBlockBinding(pipeline->shader_id, blockIndex, s_binding_point); - } - ubo_buf->ubo_binding_point = s_binding_point++; - ubo_buf->name = binding.label; - assert(s_binding_point < GL_MAX_UNIFORM_BUFFER_BINDINGS); - } - } - } - pipeline->uniform_count = ubo_count; - - pipeline->renderpass = description.renderpass; - pipeline->wireframe = description.wireframe; - - return pipeline; -} -void gpu_pipeline_destroy(gpu_pipeline* pipeline) {} - -// --- Renderpass -gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description) { - gpu_renderpass* renderpass = renderpass_pool_alloc(&context.gpu_pools.renderpasses, NULL); - memcpy(&renderpass->description, description, sizeof(gpu_renderpass_desc)); - bool default_framebuffer = description->default_framebuffer; - - if (!default_framebuffer) { - GLuint gl_fbo_id; - glGenFramebuffers(1, &gl_fbo_id); - renderpass->fbo = gl_fbo_id; - } else { - renderpass->fbo = OPENGL_DEFAULT_FRAMEBUFFER; - assert(!description->has_color_target); - assert(!description->has_depth_stencil); - } - glBindFramebuffer(GL_FRAMEBUFFER, renderpass->fbo); - - if (description->has_color_target && !default_framebuffer) { - gpu_texture* colour_attachment = TEXTURE_GET(description->color_target); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - colour_attachment->id, 0); - } - if (description->has_depth_stencil && !default_framebuffer) { - gpu_texture* depth_attachment = TEXTURE_GET(description->depth_stencil); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_attachment->id, - 0); - } - - if (description->has_depth_stencil && !description->has_color_target) { - glDrawBuffer(GL_NONE); - glReadBuffer(GL_NONE); - } - - glBindFramebuffer(GL_FRAMEBUFFER, 0); // reset to default framebuffer - - return renderpass; -} -void gpu_renderpass_destroy(gpu_renderpass* pass) { glDeleteFramebuffers(1, &pass->fbo); } - -// --- Command buffer -gpu_cmd_encoder gpu_cmd_encoder_create() { - gpu_cmd_encoder encoder = { 0 }; - return encoder; -} -void gpu_cmd_encoder_destroy(gpu_cmd_encoder* encoder) {} -void gpu_cmd_encoder_begin(gpu_cmd_encoder encoder) {} -void gpu_cmd_encoder_begin_render(gpu_cmd_encoder* encoder, gpu_renderpass* renderpass) { - glBindFramebuffer(GL_FRAMEBUFFER, renderpass->fbo); - rgba clear_colour = STONE_800; - glClearColor(clear_colour.r, clear_colour.g, clear_colour.b, 1.0f); - if (renderpass->description.has_depth_stencil) { - glClear(GL_DEPTH_BUFFER_BIT); - } else { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } -} -void gpu_cmd_encoder_end_render(gpu_cmd_encoder* encoder) { glBindFramebuffer(GL_FRAMEBUFFER, 0); } -void gpu_cmd_encoder_begin_compute() {} -gpu_cmd_encoder* gpu_get_default_cmd_encoder() { return &context.command_buffer; } - -/** @brief Finish recording and return a command buffer that can be submitted to a queue */ -gpu_cmd_buffer gpu_cmd_encoder_finish(gpu_cmd_encoder* encoder) {} - -void gpu_queue_submit(gpu_cmd_buffer* buffer) {} - -// --- Data copy commands -/** @brief Copy data from one buffer to another */ -void encode_buffer_copy(gpu_cmd_encoder* encoder, buffer_handle src, u64 src_offset, - buffer_handle dst, u64 dst_offset, u64 copy_size) {} -/** @brief Upload CPU-side data as array of bytes to a GPU buffer */ -void buffer_upload_bytes(buffer_handle gpu_buf, bytebuffer cpu_buf, u64 offset, u64 size) { - // TODO: finish implementing this - gpu_buffer* buf = BUFFER_GET(gpu_buf); -} - -/** @brief Copy data from buffer to buffer using a one time submit command buffer and a wait */ -void copy_buffer_to_buffer_oneshot(buffer_handle src, u64 src_offset, buffer_handle dst, - u64 dst_offset, u64 copy_size) {} -/** @brief Copy data from buffer to an image using a one time submit command buffer */ -void copy_buffer_to_image_oneshot(buffer_handle src, texture_handle dst) {} - -// --- Render commands -void encode_bind_pipeline(gpu_cmd_encoder* encoder, pipeline_kind kind, gpu_pipeline* pipeline) { - encoder->pipeline = pipeline; - - if (pipeline->wireframe) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - } else { - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } - - // In OpenGL binding a pipeline is more or less equivalent to just setting the shader - glUseProgram(pipeline->shader_id); -} -void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* data) { - shader_data_layout sdl = data->shader_data_get_layout(data->data); - // printf("Binding %s shader data\n", sdl.name); - - for (u32 i = 0; i < sdl.bindings_count; i++) { - shader_binding binding = sdl.bindings[i]; - /* print_shader_binding(binding); */ - - if (binding.type == SHADER_BINDING_BYTES) { - buffer_handle b; - gpu_buffer* ubo_buf; - bool found = false; - for (u32 i = 0; i < encoder->pipeline->uniform_count; i++) { - b = encoder->pipeline->uniform_bindings[i]; - ubo_buf = BUFFER_GET(b); - assert(ubo_buf->name != NULL); - if (strcmp(ubo_buf->name, binding.label) == 0) { - found = true; - break; - } - } - if (!found) { - ERROR("Couldnt find uniform buffer object!!"); - } - - i32 blockIndex = glGetUniformBlockIndex(encoder->pipeline->shader_id, binding.label); - if (blockIndex < 0) { - WARN("Couldn't retrieve block index for uniform block '%s'", binding.label); - } else { - // DEBUG("Retrived block index %d for %s", blockIndex, binding.label); - } - - glBindBuffer(GL_UNIFORM_BUFFER, ubo_buf->id.ubo); - glBufferSubData(GL_UNIFORM_BUFFER, 0, ubo_buf->size, binding.data.bytes.data); - - } else if (binding.type == SHADER_BINDING_TEXTURE) { - gpu_texture* tex = TEXTURE_GET(binding.data.texture.handle); - GLint tex_slot = glGetUniformLocation(encoder->pipeline->shader_id, binding.label); - // printf("%d slot \n", tex_slot); - if (tex_slot == GL_INVALID_VALUE || tex_slot < 0) { - WARN("Invalid binding label for texture %s - couldn't fetch texture slot uniform", - binding.label); - } - glUniform1i(tex_slot, i); - glActiveTexture(GL_TEXTURE0 + i); - glBindTexture(GL_TEXTURE_2D, tex->id); - } - } -} -void encode_set_default_settings(gpu_cmd_encoder* encoder) {} -void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) { - gpu_buffer* buffer = BUFFER_GET(buf); - if (buffer->vao == 0) { // if no VAO for this vertex buffer, create it - INFO("Setting up VAO"); - buffer->vao = opengl_bindcreate_vao(buffer, encoder->pipeline->vertex_desc); - } - glBindVertexArray(buffer->vao); -} -void encode_set_index_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) { - gpu_buffer* buffer = BUFFER_GET(buf); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->id.ibo); -} -void encode_draw(gpu_cmd_encoder* encoder, u64 count) { glDrawArrays(GL_TRIANGLES, 0, count); } -void encode_draw_indexed(gpu_cmd_encoder* encoder, u64 index_count) { - /* printf("Draw %ld indices\n", index_count); */ - glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_INT, 0); -} -void encode_clear_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) {} - -// --- Buffers -buffer_handle gpu_buffer_create(u64 size, gpu_buffer_type buf_type, gpu_buffer_flags flags, - const void* data) { - // "allocating" the cpu-side buffer struct - buffer_handle handle; - gpu_buffer* buffer = buffer_pool_alloc(&context.resource_pools->buffers, &handle); - buffer->size = size; - buffer->vao = 0; // When we create a new buffer, there will be no VAO. - - // Opengl buffer - GLuint gl_buffer_id; - glGenBuffers(1, &gl_buffer_id); - - GLenum gl_buf_type; - GLenum gl_buf_usage = GL_STATIC_DRAW; - - switch (buf_type) { - case CEL_BUFFER_UNIFORM: - DEBUG("Creating Uniform buffer"); - gl_buf_type = GL_UNIFORM_BUFFER; - /* gl_buf_usage = GL_DYNAMIC_DRAW; */ - buffer->id.ubo = gl_buffer_id; - break; - case CEL_BUFFER_DEFAULT: - case CEL_BUFFER_VERTEX: - DEBUG("Creating Vertex buffer"); - gl_buf_type = GL_ARRAY_BUFFER; - buffer->id.vbo = gl_buffer_id; - break; - case CEL_BUFFER_INDEX: - DEBUG("Creating Index buffer"); - gl_buf_type = GL_ELEMENT_ARRAY_BUFFER; - buffer->id.ibo = gl_buffer_id; - break; - default: - WARN("Unimplemented gpu_buffer_type provided %s", buffer_type_names[buf_type]); - break; - } - // bind buffer - glBindBuffer(gl_buf_type, gl_buffer_id); - - if (data) { - TRACE("Upload data (%d bytes) as part of buffer creation", size); - glBufferData(gl_buf_type, buffer->size, data, gl_buf_usage); - } else { - TRACE("Allocating but not uploading (%d bytes)", size); - glBufferData(gl_buf_type, buffer->size, NULL, gl_buf_usage); - } - - glBindBuffer(gl_buf_type, 0); - - return handle; -} - -texture_handle gpu_texture_create(texture_desc desc, bool create_view, const void* data) { - // "allocating" the cpu-side struct - texture_handle handle; - gpu_texture* texture = texture_pool_alloc(&context.resource_pools->textures, &handle); - DEBUG("Allocated texture with handle %d", handle.raw); - - GLuint gl_texture_id; - glGenTextures(1, &gl_texture_id); - texture->id = gl_texture_id; - - glBindTexture(GL_TEXTURE_2D, gl_texture_id); - - GLint internal_format = - desc.format == CEL_TEXTURE_FORMAT_DEPTH_DEFAULT ? GL_DEPTH_COMPONENT : GL_RGB; - GLenum format = desc.format == CEL_TEXTURE_FORMAT_DEPTH_DEFAULT ? GL_DEPTH_COMPONENT : GL_RGBA; - GLenum data_type = desc.format == CEL_TEXTURE_FORMAT_DEPTH_DEFAULT ? GL_FLOAT : GL_UNSIGNED_BYTE; - - if (desc.format == CEL_TEXTURE_FORMAT_DEPTH_DEFAULT) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - } else { - // set the texture wrapping parameters - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - // set texture filtering parameters - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - - if (data) { - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.extents.x, desc.extents.y, 0, format, - data_type, data); - glGenerateMipmap(GL_TEXTURE_2D); - } else { - WARN("No image data provided"); - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.extents.x, desc.extents.y, 0, format, - data_type, NULL); - } - - glBindTexture(GL_TEXTURE_2D, 0); - - return handle; -} - -void gpu_texture_destroy(texture_handle) {} -void gpu_texture_upload(texture_handle texture, const void* data) {} - -// --- Vertex formats -bytebuffer vertices_as_bytebuffer(arena* a, vertex_format format, vertex_darray* vertices) {} - -// --- TEMP -bool gpu_backend_begin_frame() { - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - return true; -} -void gpu_backend_end_frame() { - // TODO: Reset all bindings - glfwSwapBuffers(context.window); -} -void gpu_temp_draw(size_t n_verts) {} - -u32 shader_create_separate(const char* vert_shader, const char* frag_shader) { - INFO("Load shaders at %s and %s", vert_shader, frag_shader); - int success; - char info_log[512]; - - u32 vertex = glCreateShader(GL_VERTEX_SHADER); - const char* vertex_shader_src = string_from_file(vert_shader); - if (vertex_shader_src == NULL) { - ERROR("EXIT: couldnt load shader"); - exit(-1); - } - glShaderSource(vertex, 1, &vertex_shader_src, NULL); - glCompileShader(vertex); - glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); - if (!success) { - glGetShaderInfoLog(vertex, 512, NULL, info_log); - printf("%s\n", info_log); - ERROR("EXIT: vertex shader compilation failed"); - exit(-1); - } - - // fragment shader - u32 fragment = glCreateShader(GL_FRAGMENT_SHADER); - const char* fragment_shader_src = string_from_file(frag_shader); - if (fragment_shader_src == NULL) { - ERROR("EXIT: couldnt load shader"); - exit(-1); - } - glShaderSource(fragment, 1, &fragment_shader_src, NULL); - glCompileShader(fragment); - glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); - if (!success) { - glGetShaderInfoLog(fragment, 512, NULL, info_log); - printf("%s\n", info_log); - ERROR("EXIT: fragment shader compilation failed"); - exit(-1); - } - - u32 shader_prog; - shader_prog = glCreateProgram(); - - glAttachShader(shader_prog, vertex); - glAttachShader(shader_prog, fragment); - glLinkProgram(shader_prog); - glDeleteShader(vertex); - glDeleteShader(fragment); - free((char*)vertex_shader_src); - free((char*)fragment_shader_src); - - return shader_prog; -} - -inline void uniform_vec3f(u32 program_id, const char* uniform_name, vec3* value) { - glUniform3fv(glGetUniformLocation(program_id, uniform_name), 1, &value->x); -} -inline void uniform_f32(u32 program_id, const char* uniform_name, f32 value) { - glUniform1f(glGetUniformLocation(program_id, uniform_name), value); -} -inline void uniform_i32(u32 program_id, const char* uniform_name, i32 value) { - glUniform1i(glGetUniformLocation(program_id, uniform_name), value); -} -inline void uniform_mat4f(u32 program_id, const char* uniform_name, mat4* value) { - glUniformMatrix4fv(glGetUniformLocation(program_id, uniform_name), 1, GL_FALSE, value->data); -} - -// void clear_screen(vec3 colour) { -// glClearColor(colour.x, colour.y, colour.z, 1.0f); -// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -// } - -// void texture_data_upload(texture *tex) { -// printf("Texture name %s\n", tex->name); -// TRACE("Upload texture data"); -// u32 texture_id; -// glGenTextures(1, &texture_id); -// glBindTexture(GL_TEXTURE_2D, texture_id); -// tex->texture_id = texture_id; - -// // set the texture wrapping parameters -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, -// GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); -// // set texture filtering parameters -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - -// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex->width, tex->height, 0, tex->channel_type, -// GL_UNSIGNED_BYTE, tex->image_data); -// glGenerateMipmap(GL_TEXTURE_2D); -// DEBUG("Freeing texture image data after uploading to GPU"); -// // stbi_image_free(tex->image_data); // data is on gpu now so we dont need it around -// } - -// void bind_texture(shader s, texture *tex, u32 slot) { -// // printf("bind texture slot %d with texture id %d \n", slot, tex->texture_id); -// glActiveTexture(GL_TEXTURE0 + slot); -// glBindTexture(GL_TEXTURE_2D, tex->texture_id); -// } - -// void bind_mesh_vertex_buffer(void *_backend, mesh *mesh) { glBindVertexArray(mesh->vao); } - -// static inline GLenum to_gl_prim_topology(enum cel_primitive_topology primitive) { -// switch (primitive) { -// case CEL_PRIMITIVE_TOPOLOGY_TRIANGLE: -// return GL_TRIANGLES; -// case CEL_PRIMITIVE_TOPOLOGY_POINT: -// case CEL_PRIMITIVE_TOPOLOGY_LINE: -// case CEL_PRIMITIVE_TOPOLOGY_LINE_STRIP: -// case CEL_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: -// case CEL_PRIMITIVE_TOPOLOGY_COUNT: -// break; -// } -// } -#endif diff --git a/src/render/archive/backends/opengl/backend_opengl.h b/src/render/archive/backends/opengl/backend_opengl.h deleted file mode 100644 index 14b44af..0000000 --- a/src/render/archive/backends/opengl/backend_opengl.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#ifdef CEL_REND_BACKEND_OPENGL - -#include "defines.h" -#include "maths_types.h" -#include "ral.h" -#include "ral_types.h" - -#define MAX_PIPELINE_UNIFORM_BUFFERS 32 - -#define OPENGL_DEFAULT_FRAMEBUFFER 0 - -typedef struct gpu_swapchain { - u32x2 dimensions; -} gpu_swapchain; -typedef struct gpu_device { -} gpu_device; -typedef struct gpu_pipeline_layout { - void* pad -} gpu_pipeline_layout; -typedef struct gpu_pipeline { - u32 shader_id; - gpu_renderpass* renderpass; - vertex_description vertex_desc; - buffer_handle uniform_bindings[MAX_PIPELINE_UNIFORM_BUFFERS]; - u32 uniform_count; - bool wireframe; -} gpu_pipeline; -typedef struct gpu_renderpass { - u32 fbo; - gpu_renderpass_desc description; -} gpu_renderpass; -typedef struct gpu_cmd_encoder { - gpu_pipeline* pipeline; -} gpu_cmd_encoder; // Recording -typedef struct gpu_cmd_buffer { - void* pad; -} gpu_cmd_buffer; // Ready for submission - -typedef struct gpu_buffer { - union { - u32 vbo; - u32 ibo; - u32 ubo; - } id; - union { - u32 vao; - u32 ubo_binding_point - }; // Optional - char* name; - u64 size; -} gpu_buffer; -typedef struct gpu_texture { - u32 id; - void* pad; -} gpu_texture; - -typedef struct opengl_support { -} opengl_support; - -u32 shader_create_separate(const char* vert_shader, const char* frag_shader); - -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 diff --git a/src/render/archive/backends/vulkan/README.md b/src/render/archive/backends/vulkan/README.md deleted file mode 100644 index 220ed64..0000000 --- a/src/render/archive/backends/vulkan/README.md +++ /dev/null @@ -1 +0,0 @@ -# Vulkan Backend Overview
\ No newline at end of file diff --git a/src/render/archive/backends/vulkan/backend_vulkan.c b/src/render/archive/backends/vulkan/backend_vulkan.c deleted file mode 100644 index 8801230..0000000 --- a/src/render/archive/backends/vulkan/backend_vulkan.c +++ /dev/null @@ -1,1705 +0,0 @@ -#include "defines.h" -#if defined(CEL_REND_BACKEND_VULKAN) - -#define GLFW_INCLUDE_VULKAN -#include <glfw3.h> - -#include <assert.h> -#include <stddef.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <vulkan/vk_platform.h> -#include <vulkan/vulkan.h> -#include <vulkan/vulkan_core.h> - -#include "backend_vulkan.h" -#include "buf.h" -#include "darray.h" -#include "maths_types.h" -#include "mem.h" -#include "ral_types.h" -#include "str.h" -#include "vulkan_helpers.h" - -#include "file.h" -#include "log.h" -#include "ral.h" -#include "utils.h" - -// TEMP -#define SCREEN_WIDTH 1000 -#define SCREEN_HEIGHT 1000 -#define VULKAN_QUEUES_COUNT 2 -#define MAX_DESCRIPTOR_SETS 10 - -const char* queue_names[VULKAN_QUEUES_COUNT] = { "GRAPHICS", "TRANSFER" }; - -KITC_DECL_TYPED_ARRAY(VkDescriptorSet) - -typedef struct vulkan_context { - VkInstance instance; - VkAllocationCallbacks* allocator; - VkSurfaceKHR surface; - vulkan_swapchain_support_info swapchain_support; - - arena temp_arena; - arena pool_arena; - gpu_device* device; - gpu_swapchain* swapchain; - u32 framebuffer_count; - VkFramebuffer* - swapchain_framebuffers; // TODO: Move this data into the swapchain as its own struct - - u32 current_img_index; - u32 current_frame; // super important - gpu_cmd_encoder main_cmd_bufs[MAX_FRAMES_IN_FLIGHT]; - VkSemaphore image_available_semaphores[MAX_FRAMES_IN_FLIGHT]; - VkSemaphore render_finished_semaphores[MAX_FRAMES_IN_FLIGHT]; - VkFence in_flight_fences[MAX_FRAMES_IN_FLIGHT]; - - // HACK - VkRenderPass main_renderpass; - - u32 screen_width; - u32 screen_height; - bool is_resizing; - GLFWwindow* window; - - // Storage - gpu_buffer buffers[1024]; - size_t buffer_count; - VkDescriptorSet_darray* free_set_queue; - struct resource_pools* resource_pools; - gpu_backend_pools gpu_pools; - - VkDebugUtilsMessengerEXT vk_debugger; -} vulkan_context; - -static vulkan_context context; - -// --- Function forward declarations - -void backend_pools_init(arena* a, gpu_backend_pools* backend_pools); - -/** @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); -void create_swapchain_framebuffers(); -void create_sync_objects(); -void create_descriptor_pools(); -size_t vertex_attrib_size(vertex_attrib_type attr); - -VkShaderModule create_shader_module(str8 spirv); - -/** @brief Helper function for creating array of all extensions we want */ -cstr_darray* get_all_extensions(); - -VkImage vulkan_image_create(u32x2 dimensions, VkImageType image_type, VkFormat format, - VkImageUsageFlags usage); -void vulkan_transition_image_layout(gpu_texture* texture, VkFormat format, VkImageLayout old_layout, - VkImageLayout new_layout); - -// --- Handy macros -#define BUFFER_GET(h) (buffer_pool_get(&context.resource_pools->buffers, h)) -#define TEXTURE_GET(h) (texture_pool_get(&context.resource_pools->textures, h)) - -bool gpu_backend_init(const char* window_name, GLFWwindow* window) { - memset(&context, 0, sizeof(vulkan_context)); - context.allocator = 0; // TODO: use an allocator - context.screen_width = SCREEN_WIDTH; - context.screen_height = SCREEN_HEIGHT; - context.window = window; - context.current_img_index = 0; - context.current_frame = 0; - context.free_set_queue = VkDescriptorSet_darray_new(100); - - // Create an allocator - size_t temp_arena_size = 1024 * 1024; - context.temp_arena = arena_create(malloc(temp_arena_size), temp_arena_size); - - size_t pool_buffer_size = 1024 * 1024; - context.pool_arena = arena_create(malloc(pool_buffer_size), pool_buffer_size); - - backend_pools_init(&context.pool_arena, &context.gpu_pools); - - // Setup Vulkan instance - VkApplicationInfo app_info = { VK_STRUCTURE_TYPE_APPLICATION_INFO }; - app_info.apiVersion = VK_API_VERSION_1_2; - app_info.pApplicationName = 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; - - // Extensions - cstr_darray* required_extensions = cstr_darray_new(2); - // cstr_darray_push(required_extensions, VK_KHR_SURFACE_EXTENSION_NAME); - - uint32_t count; - const char** extensions = glfwGetRequiredInstanceExtensions(&count); - 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); - return false; - } - 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)); - context.surface = surface; - TRACE("Vulkan Surface created"); - - return true; -} - -void gpu_backend_shutdown() { - gpu_swapchain_destroy(context.swapchain); - - vkDestroySurfaceKHR(context.instance, context.surface, context.allocator); - vkDestroyInstance(context.instance, context.allocator); - 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"); - - // Logical device & Queues - create_logical_device(out_device); - - // Create the command pool - VkCommandPoolCreateInfo pool_create_info = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO }; - pool_create_info.queueFamilyIndex = out_device->queue_family_indicies.graphics_family_index; - pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - vkCreateCommandPool(out_device->logical_device, &pool_create_info, context.allocator, - &out_device->pool); - TRACE("Command Pool created"); - - // Synchronisation objects - create_sync_objects(); - TRACE("Synchronisation primitives created"); - - arena_rewind(savept); // Free any temp data - return true; -} - -bool gpu_swapchain_create(gpu_swapchain* out_swapchain) { - context.swapchain = out_swapchain; - - out_swapchain->swapchain_arena = arena_create(malloc(1024), 1024); - - vulkan_device_query_swapchain_support(context.device->physical_device, context.surface, - &context.swapchain_support); - vulkan_swapchain_support_info swapchain_support = context.swapchain_support; - - // TODO: custom swapchain extents VkExtent2D swapchain_extent = { width, height }; - - VkSurfaceFormatKHR image_format = choose_swapchain_format(&swapchain_support); - out_swapchain->image_format = image_format; - VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR; // guaranteed to be implemented - out_swapchain->present_mode = present_mode; - - u32 image_count = swapchain_support.capabilities.minImageCount + 1; - out_swapchain->image_count = image_count; - - VkSwapchainCreateInfoKHR swapchain_create_info = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR }; - swapchain_create_info.surface = context.surface; - swapchain_create_info.minImageCount = image_count; - swapchain_create_info.imageFormat = image_format.format; - swapchain_create_info.imageColorSpace = image_format.colorSpace; - swapchain_create_info.imageExtent = swapchain_support.capabilities.currentExtent; - swapchain_create_info.imageArrayLayers = 1; - swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - swapchain_create_info.queueFamilyIndexCount = 0; - swapchain_create_info.pQueueFamilyIndices = NULL; - - swapchain_create_info.preTransform = swapchain_support.capabilities.currentTransform; - swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - swapchain_create_info.presentMode = present_mode; - swapchain_create_info.clipped = VK_TRUE; - swapchain_create_info.oldSwapchain = VK_NULL_HANDLE; - - out_swapchain->extent = swapchain_support.capabilities.currentExtent; - - VK_CHECK(vkCreateSwapchainKHR(context.device->logical_device, &swapchain_create_info, - context.allocator, &out_swapchain->handle)); - TRACE("Vulkan Swapchain created"); - - // Retrieve Images - // out_swapchain->images = - // arena_alloc(&out_swapchain->swapchain_arena, image_count * sizeof(VkImage)); - out_swapchain->images = malloc(image_count * sizeof(VkImage)); - VK_CHECK(vkGetSwapchainImagesKHR(context.device->logical_device, out_swapchain->handle, - &image_count, out_swapchain->images)); - - // Create ImageViews - // TODO: Move this to a separate function - out_swapchain->image_views = malloc(image_count * sizeof(VkImageView)); - // arena_alloc(&out_swapchain->swapchain_arena, image_count * sizeof(VkImageView)); - for (u32 i = 0; i < image_count; i++) { - VkImageViewCreateInfo view_create_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; - view_create_info.image = out_swapchain->images[i]; - view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - view_create_info.format = image_format.format; - view_create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - view_create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - view_create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - view_create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - view_create_info.subresourceRange.baseMipLevel = 0; - view_create_info.subresourceRange.levelCount = 1; - view_create_info.subresourceRange.baseArrayLayer = 0; - view_create_info.subresourceRange.layerCount = 1; - vkCreateImageView(context.device->logical_device, &view_create_info, context.allocator, - &out_swapchain->image_views[i]); - } - - return true; -} - -void gpu_swapchain_destroy(gpu_swapchain* swapchain) { - // Destroy Framebuffers - DEBUG("Image count %d", swapchain->image_count); - for (u32 i = 0; i < swapchain->image_count; i++) { - DEBUG("Framebuffer handle %d", context.swapchain_framebuffers[i]); - vkDestroyFramebuffer(context.device->logical_device, context.swapchain_framebuffers[i], - context.allocator); - } - for (u32 i = 0; i < swapchain->image_count; i++) { - vkDestroyImageView(context.device->logical_device, swapchain->image_views[i], - context.allocator); - } - arena_free_all(&swapchain->swapchain_arena); - vkDestroySwapchainKHR(context.device->logical_device, swapchain->handle, context.allocator); - TRACE("Vulkan Swapchain destroyed"); -} - -static void recreate_swapchain(gpu_swapchain* swapchain) { - int width = 0, height = 0; - glfwGetFramebufferSize(context.window, &width, &height); - while (width == 0 || height == 0) { - glfwGetFramebufferSize(context.window, &width, &height); - glfwWaitEvents(); - } - DEBUG("Recreating swapchain..."); - vkDeviceWaitIdle(context.device->logical_device); - - gpu_swapchain_destroy(swapchain); - gpu_swapchain_create(swapchain); - create_swapchain_framebuffers(); -} - -VkFormat format_from_vertex_attr(vertex_attrib_type attr) { - switch (attr) { - case ATTR_F32: - return VK_FORMAT_R32_SFLOAT; - case ATTR_U32: - return VK_FORMAT_R32_UINT; - case ATTR_I32: - return VK_FORMAT_R32_SINT; - case ATTR_F32x2: - return VK_FORMAT_R32G32_SFLOAT; - case ATTR_U32x2: - return VK_FORMAT_R32G32_UINT; - case ATTR_I32x2: - return VK_FORMAT_R32G32_UINT; - case ATTR_F32x3: - return VK_FORMAT_R32G32B32_SFLOAT; - case ATTR_U32x3: - return VK_FORMAT_R32G32B32_UINT; - case ATTR_I32x3: - return VK_FORMAT_R32G32B32_SINT; - case ATTR_F32x4: - return VK_FORMAT_R32G32B32A32_SFLOAT; - case ATTR_U32x4: - return VK_FORMAT_R32G32B32A32_UINT; - case ATTR_I32x4: - return VK_FORMAT_R32G32B32A32_SINT; - } -} - -gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description) { - TRACE("GPU Graphics Pipeline creation"); - // Allocate - gpu_pipeline_layout* layout = - pipeline_layout_pool_alloc(&context.gpu_pools.pipeline_layouts, NULL); - gpu_pipeline* pipeline = pipeline_pool_alloc(&context.gpu_pools.pipelines, NULL); - - // Shaders - printf("Vertex shader: %s\n", description.vs.filepath.buf); - printf("Fragment shader: %s\n", description.fs.filepath.buf); - VkShaderModule vertex_shader = create_shader_module(description.vs.code); - VkShaderModule fragment_shader = create_shader_module(description.fs.code); - - // Vertex - VkPipelineShaderStageCreateInfo vert_shader_stage_info = { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO - }; - vert_shader_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT; - vert_shader_stage_info.module = vertex_shader; - vert_shader_stage_info.pName = "main"; - // Fragment - VkPipelineShaderStageCreateInfo frag_shader_stage_info = { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO - }; - frag_shader_stage_info.stage = VK_SHADER_STAGE_FRAGMENT_BIT; - frag_shader_stage_info.module = fragment_shader; - frag_shader_stage_info.pName = "main"; - - VkPipelineShaderStageCreateInfo shader_stages[2] = { vert_shader_stage_info, - frag_shader_stage_info }; - - // Attributes - u32 attr_count = description.vertex_desc.attributes_count; - printf("N attributes %d\n", attr_count); - VkVertexInputAttributeDescription attribute_descs[attr_count]; - memset(attribute_descs, 0, attr_count * sizeof(VkVertexInputAttributeDescription)); - 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].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); - printf("sizeof vertex %ld\n", sizeof(vertex)); - offset += this_offset; - } - - // Vertex input - // TODO: Generate this from descroiption now - VkVertexInputBindingDescription binding_desc; - binding_desc.binding = 0; - binding_desc.stride = description.vertex_desc.use_full_vertex_size - ? sizeof(vertex) - : description.vertex_desc.stride; - binding_desc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - VkPipelineVertexInputStateCreateInfo vertex_input_info = { - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO - }; - vertex_input_info.vertexBindingDescriptionCount = 1; - vertex_input_info.pVertexBindingDescriptions = &binding_desc; - vertex_input_info.vertexAttributeDescriptionCount = - attr_count; // description.vertex_desc.attributes_count; - vertex_input_info.pVertexAttributeDescriptions = attribute_descs; - - // Input Assembly - VkPipelineInputAssemblyStateCreateInfo input_assembly = { - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO - }; - input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - input_assembly.primitiveRestartEnable = VK_FALSE; - - // Viewport - VkViewport viewport = { .x = 0, - .y = 0, - .width = (f32)context.swapchain->extent.width, - .height = (f32)context.swapchain->extent.height, - .minDepth = 0.0, - .maxDepth = 1.0 }; - VkRect2D scissor = { .offset = { .x = 0, .y = 0 }, .extent = context.swapchain->extent }; - VkPipelineViewportStateCreateInfo viewport_state = { - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO - }; - viewport_state.viewportCount = 1; - // viewport_state.pViewports = &viewport; - viewport_state.scissorCount = 1; - // viewport_state.pScissors = &scissor; - - // Rasterizer - VkPipelineRasterizationStateCreateInfo rasterizer_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO - }; - rasterizer_create_info.depthClampEnable = VK_FALSE; - rasterizer_create_info.rasterizerDiscardEnable = VK_FALSE; - rasterizer_create_info.polygonMode = - description.wireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL; - rasterizer_create_info.lineWidth = 1.0f; - rasterizer_create_info.cullMode = VK_CULL_MODE_BACK_BIT; - rasterizer_create_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - /* rasterizer_create_info.frontFace = VK_FRONT_FACE_CLOCKWISE; */ - rasterizer_create_info.depthBiasEnable = VK_FALSE; - rasterizer_create_info.depthBiasConstantFactor = 0.0; - rasterizer_create_info.depthBiasClamp = 0.0; - rasterizer_create_info.depthBiasSlopeFactor = 0.0; - - // Multisampling - VkPipelineMultisampleStateCreateInfo ms_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO - }; - ms_create_info.sampleShadingEnable = VK_FALSE; - ms_create_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - ms_create_info.minSampleShading = 1.0; - ms_create_info.pSampleMask = 0; - ms_create_info.alphaToCoverageEnable = VK_FALSE; - ms_create_info.alphaToOneEnable = VK_FALSE; - - // TODO: Depth and stencil testing - // VkPipelineDepthStencilStateCreateInfo depth_stencil = { - // VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO - // }; - // depth_stencil.depthTestEnable = description.depth_test ? VK_TRUE : VK_FALSE; - // depth_stencil.depthWriteEnable = description.depth_test ? VK_TRUE : VK_FALSE; - // depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS; - // depth_stencil.depthBoundsTestEnable = VK_FALSE; - // depth_stencil.stencilTestEnable = VK_FALSE; - // depth_stencil.pNext = 0; - - // Blending - VkPipelineColorBlendAttachmentState color_blend_attachment_state; - color_blend_attachment_state.blendEnable = VK_FALSE; - color_blend_attachment_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - color_blend_attachment_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - color_blend_attachment_state.colorBlendOp = VK_BLEND_OP_ADD; - color_blend_attachment_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - color_blend_attachment_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - color_blend_attachment_state.alphaBlendOp = VK_BLEND_OP_ADD; - color_blend_attachment_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | - VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - - VkPipelineColorBlendStateCreateInfo color_blend = { - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO - }; - color_blend.logicOpEnable = VK_FALSE; - color_blend.logicOp = VK_LOGIC_OP_COPY; - color_blend.attachmentCount = 1; - color_blend.pAttachments = &color_blend_attachment_state; - -// Dynamic state -#define DYNAMIC_STATE_COUNT 2 - VkDynamicState dynamic_states[DYNAMIC_STATE_COUNT] = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - }; - - VkPipelineDynamicStateCreateInfo dynamic_state = { - VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO - }; - dynamic_state.dynamicStateCount = DYNAMIC_STATE_COUNT; - dynamic_state.pDynamicStates = dynamic_states; - - // Descriptor Set layouts - - VkDescriptorSetLayout* desc_set_layouts = - malloc(description.data_layouts_count * sizeof(VkDescriptorSetLayout)); - pipeline->desc_set_layouts = desc_set_layouts; - pipeline->desc_set_layouts_count = description.data_layouts_count; - if (description.data_layouts_count > 0) { - pipeline->uniform_pointers = - malloc(description.data_layouts_count * sizeof(desc_set_uniform_buffer)); - } else { - pipeline->uniform_pointers = NULL; - } - - // assert(description.data_layouts_count == 1); - printf("data layouts %d\n", description.data_layouts_count); - for (u32 layout_i = 0; layout_i < description.data_layouts_count; layout_i++) { - shader_data_layout sdl = description.data_layouts[layout_i].shader_data_get_layout(NULL); - TRACE("Got shader data layout %d's bindings! . found %d", layout_i, sdl.bindings_count); - - VkDescriptorSetLayoutBinding desc_set_bindings[sdl.bindings_count]; - - // Bindings - assert(sdl.bindings_count == 2); - for (u32 binding_j = 0; binding_j < sdl.bindings_count; binding_j++) { - desc_set_bindings[binding_j].binding = binding_j; - desc_set_bindings[binding_j].descriptorCount = 1; - switch (sdl.bindings[binding_j].type) { - case SHADER_BINDING_BUFFER: - case SHADER_BINDING_BYTES: - desc_set_bindings[binding_j].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - desc_set_bindings[binding_j].stageFlags = - VK_SHADER_STAGE_VERTEX_BIT; // FIXME: dont hardcode - - u64 buffer_size = sdl.bindings[binding_j].data.bytes.size; - VkDeviceSize uniform_buf_size = buffer_size; - // TODO: Create backing buffer - - VkBuffer buffers[MAX_FRAMES_IN_FLIGHT]; - VkDeviceMemory uniform_buf_memorys[MAX_FRAMES_IN_FLIGHT]; - void* uniform_buf_mem_mappings[MAX_FRAMES_IN_FLIGHT]; - // void* s? - for (size_t frame_i = 0; frame_i < MAX_FRAMES_IN_FLIGHT; frame_i++) { - buffer_handle uniform_buf_handle = - gpu_buffer_create(buffer_size, CEL_BUFFER_UNIFORM, CEL_BUFFER_FLAG_CPU, NULL); - - gpu_buffer* created_gpu_buffer = - BUFFER_GET(uniform_buf_handle); // context.buffers[uniform_buf_handle.raw]; - buffers[frame_i] = created_gpu_buffer->handle; - uniform_buf_memorys[frame_i] = created_gpu_buffer->memory; - vkMapMemory(context.device->logical_device, uniform_buf_memorys[frame_i], 0, - uniform_buf_size, 0, &uniform_buf_mem_mappings[frame_i]); - // now we have a pointer in unifrom_buf_mem_mappings we can write to - } - - desc_set_uniform_buffer uniform_data; - memcpy(&uniform_data.buffers, &buffers, sizeof(buffers)); - memcpy(&uniform_data.uniform_buf_memorys, &uniform_buf_memorys, - sizeof(uniform_buf_memorys)); - memcpy(&uniform_data.uniform_buf_mem_mappings, &uniform_buf_mem_mappings, - sizeof(uniform_buf_mem_mappings)); - uniform_data.size = buffer_size; - - pipeline->uniform_pointers[binding_j] = uniform_data; - - break; - case SHADER_BINDING_TEXTURE: - desc_set_bindings[binding_j].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - desc_set_bindings[binding_j].stageFlags = - VK_SHADER_STAGE_FRAGMENT_BIT; // FIXME: dont hardcode - desc_set_bindings[binding_j].pImmutableSamplers = NULL; - - break; - default: - ERROR_EXIT("Unimplemented binding type!! in backend_vulkan"); - } - switch (sdl.bindings[binding_j].vis) { - case VISIBILITY_VERTEX: - desc_set_bindings[binding_j].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - break; - case VISIBILITY_FRAGMENT: - desc_set_bindings[binding_j].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - break; - case VISIBILITY_COMPUTE: - WARN("Compute is not implemented yet"); - break; - } - } - - VkDescriptorSetLayoutCreateInfo desc_set_layout_info = { - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO - }; - desc_set_layout_info.bindingCount = sdl.bindings_count; - desc_set_layout_info.pBindings = desc_set_bindings; - - VK_CHECK(vkCreateDescriptorSetLayout(context.device->logical_device, &desc_set_layout_info, - context.allocator, &desc_set_layouts[layout_i])); - } - printf("Descriptor set layouts\n"); - - // Layout - VkPipelineLayoutCreateInfo pipeline_layout_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO - }; - pipeline_layout_create_info.setLayoutCount = description.data_layouts_count; - pipeline_layout_create_info.pSetLayouts = desc_set_layouts; - pipeline_layout_create_info.pushConstantRangeCount = 0; - pipeline_layout_create_info.pPushConstantRanges = NULL; - VK_CHECK(vkCreatePipelineLayout(context.device->logical_device, &pipeline_layout_create_info, - context.allocator, &layout->handle)); - pipeline->layout_handle = layout->handle; // keep a copy of the layout on the pipeline object - - VkGraphicsPipelineCreateInfo pipeline_create_info = { - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO - }; - - pipeline_create_info.stageCount = 2; - pipeline_create_info.pStages = shader_stages; - pipeline_create_info.pVertexInputState = &vertex_input_info; - pipeline_create_info.pInputAssemblyState = &input_assembly; - - pipeline_create_info.pViewportState = &viewport_state; - pipeline_create_info.pRasterizationState = &rasterizer_create_info; - pipeline_create_info.pMultisampleState = &ms_create_info; - pipeline_create_info.pDepthStencilState = NULL; // &depth_stencil; - pipeline_create_info.pColorBlendState = &color_blend; - pipeline_create_info.pDynamicState = &dynamic_state; - pipeline_create_info.pTessellationState = 0; - - pipeline_create_info.layout = layout->handle; - - pipeline_create_info.renderPass = description.renderpass->handle; - pipeline_create_info.subpass = 0; - pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; - pipeline_create_info.basePipelineIndex = -1; - - printf("About to create graphics pipeline\n"); - - VkResult result = - vkCreateGraphicsPipelines(context.device->logical_device, VK_NULL_HANDLE, 1, - &pipeline_create_info, context.allocator, &pipeline->handle); - if (result != VK_SUCCESS) { - FATAL("graphics pipeline creation failed. its fked mate"); - ERROR_EXIT("Doomed"); - } - TRACE("Vulkan Graphics pipeline created"); - - // once the pipeline has been created we can destroy these - vkDestroyShaderModule(context.device->logical_device, vertex_shader, context.allocator); - vkDestroyShaderModule(context.device->logical_device, fragment_shader, context.allocator); - - // Framebuffers - create_swapchain_framebuffers(); - TRACE("Swapchain Framebuffers created"); - - for (u32 frame_i = 0; frame_i < MAX_FRAMES_IN_FLIGHT; frame_i++) { - context.main_cmd_bufs[frame_i] = gpu_cmd_encoder_create(); - } - TRACE("main Command Buffer created"); - - TRACE("Graphics pipeline created"); - return pipeline; -} - -void gpu_pipeline_destroy(gpu_pipeline* pipeline) { - vkDestroyPipeline(context.device->logical_device, pipeline->handle, context.allocator); - vkDestroyPipelineLayout(context.device->logical_device, pipeline->layout_handle, - context.allocator); -} - -gpu_cmd_encoder* gpu_get_default_cmd_encoder() { - return &context.main_cmd_bufs[context.current_frame]; -} - -gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description) { - gpu_renderpass* renderpass = renderpass_pool_alloc(&context.gpu_pools.renderpasses, NULL); - - // attachments - u32 attachment_desc_count = 2; - VkAttachmentDescription attachment_descriptions[2]; - - // Colour attachment - VkAttachmentDescription color_attachment; - color_attachment.format = context.swapchain->image_format.format; - color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; - color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - color_attachment.flags = 0; - - attachment_descriptions[0] = color_attachment; - - VkAttachmentReference color_attachment_reference; - color_attachment_reference.attachment = 0; - color_attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - // Depth attachment - u32x2 ext = { .x = context.swapchain_support.capabilities.currentExtent.width, - .y = context.swapchain_support.capabilities.currentExtent.height }; - texture_desc depth_desc = { .extents = ext, - .format = CEL_TEXTURE_FORMAT_DEPTH_DEFAULT, - .tex_type = CEL_TEXTURE_TYPE_2D }; - texture_handle depth_texture_handle = gpu_texture_create(depth_desc, true, NULL); - gpu_texture* depth = TEXTURE_GET(depth_texture_handle); - - VkAttachmentDescription depth_attachment; - depth_attachment.format = // TODO: context->device.depth_format; - depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT; - depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - depth_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - depth_attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - depth_attachment.flags = 0; - - attachment_descriptions[1] = depth_attachment; - - VkAttachmentReference depth_attachment_reference; - depth_attachment_reference.attachment = 1; - depth_attachment_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - // main subpass - VkSubpassDescription subpass = { 0 }; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &color_attachment_reference; - - // sets everything up - // renderpass dependencies - VkSubpassDependency dependency; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.srcAccessMask = 0; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstAccessMask = - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependency.dependencyFlags = 0; - - // Finally, create the RenderPass - VkRenderPassCreateInfo render_pass_create_info = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO }; - render_pass_create_info.attachmentCount = 1; - render_pass_create_info.pAttachments = &color_attachment; - render_pass_create_info.subpassCount = 1; - render_pass_create_info.pSubpasses = &subpass; - render_pass_create_info.dependencyCount = 1; - render_pass_create_info.pDependencies = &dependency; - render_pass_create_info.flags = 0; - render_pass_create_info.pNext = 0; - - VK_CHECK(vkCreateRenderPass(context.device->logical_device, &render_pass_create_info, - context.allocator, &renderpass->handle)); - - // HACK - context.main_renderpass = renderpass->handle; - - return renderpass; -} - -gpu_cmd_encoder gpu_cmd_encoder_create() { - // gpu_cmd_encoder* encoder = malloc(sizeof(gpu_cmd_encoder)); // TODO: fix leaking mem - gpu_cmd_encoder encoder = { 0 }; - - VkCommandBufferAllocateInfo allocate_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; - allocate_info.commandPool = context.device->pool; - allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocate_info.commandBufferCount = 1; - allocate_info.pNext = NULL; - - VK_CHECK(vkAllocateCommandBuffers(context.device->logical_device, &allocate_info, - &encoder.cmd_buffer);); - - VkDescriptorPoolSize pool_sizes[2]; - // Uniforms pool - pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - pool_sizes[0].descriptorCount = MAX_FRAMES_IN_FLIGHT * MAX_DESCRIPTOR_SETS; - // Samplers pool - pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - pool_sizes[1].descriptorCount = MAX_FRAMES_IN_FLIGHT * MAX_DESCRIPTOR_SETS; - - VkDescriptorPoolCreateInfo pool_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; - pool_info.poolSizeCount = 2; - pool_info.pPoolSizes = pool_sizes; - pool_info.maxSets = 100; - - VK_CHECK(vkCreateDescriptorPool(context.device->logical_device, &pool_info, context.allocator, - &encoder.descriptor_pool)); - - return encoder; -} -void gpu_cmd_encoder_destroy(gpu_cmd_encoder* encoder) { - vkFreeCommandBuffers(context.device->logical_device, context.device->pool, 1, - &encoder->cmd_buffer); -} - -void gpu_cmd_encoder_begin(gpu_cmd_encoder encoder) { - VK_CHECK(vkResetDescriptorPool(context.device->logical_device, encoder.descriptor_pool, 0)); - - VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; - VK_CHECK(vkBeginCommandBuffer(encoder.cmd_buffer, &begin_info)); -} - -void gpu_cmd_encoder_begin_render(gpu_cmd_encoder* encoder, gpu_renderpass* renderpass) { - VkRenderPassBeginInfo begin_info = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO }; - begin_info.renderPass = renderpass->handle; - /* printf("Current img: %d Current frame %d\n", context.current_img_index, context.current_frame); - */ - begin_info.framebuffer = context.swapchain_framebuffers[context.current_img_index]; - begin_info.renderArea.offset = (VkOffset2D){ 0, 0 }; - begin_info.renderArea.extent = context.swapchain->extent; - - // VkClearValue clear_values[2]; - VkClearValue clear_color = { { { 0.02f, 0.02f, 0.02f, 1.0f } } }; - // clear_values[1].depthStencil.depth = renderpass->depth; - // clear_values[1].depthStencil.stencil = renderpass->stencil; - - begin_info.clearValueCount = 1; - begin_info.pClearValues = &clear_color; - - vkCmdBeginRenderPass(encoder->cmd_buffer, &begin_info, VK_SUBPASS_CONTENTS_INLINE); - // command_buffer->state = COMMAND_BUFFER_STATE_IN_RENDER_PASS; -} - -void gpu_cmd_encoder_end_render(gpu_cmd_encoder* encoder) { - vkCmdEndRenderPass(encoder->cmd_buffer); -} - -gpu_cmd_buffer gpu_cmd_encoder_finish(gpu_cmd_encoder* encoder) { - vkEndCommandBuffer(encoder->cmd_buffer); - - // TEMP: submit - return (gpu_cmd_buffer){ .cmd_buffer = encoder->cmd_buffer }; -} - -// --- Binding -void encode_bind_pipeline(gpu_cmd_encoder* encoder, pipeline_kind kind, gpu_pipeline* pipeline) { - vkCmdBindPipeline(encoder->cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle); - encoder->pipeline = pipeline; -} - -void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* data) { - arena tmp = arena_create(malloc(1024), 1024); - - assert(data->data != NULL); - - // Update the local buffer - desc_set_uniform_buffer ubo = encoder->pipeline->uniform_pointers[group]; - memcpy(ubo.uniform_buf_mem_mappings[context.current_frame], data->data, ubo.size); - - VkDescriptorSetAllocateInfo alloc_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; - alloc_info.descriptorPool = encoder->descriptor_pool; - alloc_info.descriptorSetCount = 1; - alloc_info.pSetLayouts = &encoder->pipeline->desc_set_layouts[group]; - - shader_data_layout sdl = data->shader_data_get_layout(data->data); - size_t binding_count = sdl.bindings_count; - assert(binding_count == 2); - - VkDescriptorSet sets[0]; - VK_CHECK(vkAllocateDescriptorSets(context.device->logical_device, &alloc_info, sets)); - // FIXME: hardcoded - VkDescriptorSet_darray_push(context.free_set_queue, sets[0]); - /* VkDescriptorSet_darray_push(context.free_set_queue, sets[1]); */ - - VkWriteDescriptorSet write_sets[binding_count]; - memset(&write_sets, 0, binding_count * sizeof(VkWriteDescriptorSet)); - - for (u32 i = 0; i < sdl.bindings_count; i++) { - shader_binding binding = sdl.bindings[i]; - - if (binding.type == SHADER_BINDING_BUFFER || binding.type == SHADER_BINDING_BYTES) { - VkDescriptorBufferInfo* buffer_info = arena_alloc(&tmp, sizeof(VkDescriptorBufferInfo)); - buffer_info->buffer = ubo.buffers[context.current_frame]; - buffer_info->offset = 0; - buffer_info->range = binding.data.bytes.size; - - write_sets[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_sets[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - write_sets[i].descriptorCount = 1; - write_sets[i].dstSet = sets[0]; - write_sets[i].dstBinding = i; - write_sets[i].dstArrayElement = 0; - write_sets[i].pBufferInfo = buffer_info; - } else if (binding.type == SHADER_BINDING_TEXTURE) { - gpu_texture* texture = TEXTURE_GET(binding.data.texture.handle); - VkDescriptorImageInfo* image_info = arena_alloc(&tmp, sizeof(VkDescriptorImageInfo)); - image_info->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - image_info->imageView = texture->view; - image_info->sampler = texture->sampler; - - write_sets[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_sets[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - write_sets[i].descriptorCount = 1; - write_sets[i].dstSet = sets[0]; - write_sets[i].dstBinding = i; - write_sets[i].dstArrayElement = 0; - write_sets[i].pImageInfo = image_info; - } else { - WARN("Unknown binding"); - } - } - - // Update - vkUpdateDescriptorSets(context.device->logical_device, binding_count, write_sets, 0, NULL); - - // Bind - vkCmdBindDescriptorSets(encoder->cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - encoder->pipeline->layout_handle, 0, 1, sets, 0, NULL); - - arena_free_storage(&tmp); -} - -void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) { - gpu_buffer* buffer = BUFFER_GET(buf); // context.buffers[buf.raw]; - VkBuffer vbs[] = { buffer->handle }; - VkDeviceSize offsets[] = { 0 }; - vkCmdBindVertexBuffers(encoder->cmd_buffer, 0, 1, vbs, offsets); -} - -void encode_set_index_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) { - gpu_buffer* buffer = BUFFER_GET(buf); // context.buffers[buf.raw]; - vkCmdBindIndexBuffer(encoder->cmd_buffer, buffer->handle, 0, VK_INDEX_TYPE_UINT32); -} - -// TEMP -void encode_set_default_settings(gpu_cmd_encoder* encoder) { - VkViewport viewport = { 0 }; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = context.swapchain->extent.width; - viewport.height = context.swapchain->extent.height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - vkCmdSetViewport(encoder->cmd_buffer, 0, 1, &viewport); - - VkRect2D scissor = { 0 }; - scissor.offset = (VkOffset2D){ 0, 0 }; - scissor.extent = context.swapchain->extent; - vkCmdSetScissor(encoder->cmd_buffer, 0, 1, &scissor); -} - -// --- Drawing - -bool gpu_backend_begin_frame() { - u32 current_frame = context.current_frame; - vkWaitForFences(context.device->logical_device, 1, &context.in_flight_fences[current_frame], - VK_TRUE, UINT64_MAX); - - u32 image_index; - VkResult result = vkAcquireNextImageKHR( - context.device->logical_device, context.swapchain->handle, UINT64_MAX, - context.image_available_semaphores[current_frame], VK_NULL_HANDLE, &image_index); - if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || context.is_resizing) { - ERROR("Acquire next image failure. recreate swapchain"); - context.is_resizing = false; - recreate_swapchain(context.swapchain); - return false; - } else if (result != VK_SUCCESS) { - ERROR_EXIT("failed to acquire swapchain image"); - } - - vkResetFences(context.device->logical_device, 1, &context.in_flight_fences[current_frame]); - - context.current_img_index = image_index; - VK_CHECK(vkResetCommandBuffer(context.main_cmd_bufs[current_frame].cmd_buffer, 0)); - return true; -} - -void gpu_temp_draw(size_t n_indices) { - gpu_cmd_encoder* encoder = gpu_get_default_cmd_encoder(); // &context.main_cmd_buf; - /* vkCmdDraw(encoder->cmd_buffer, n_verts, 1, 0, 0); */ - vkCmdDrawIndexed(encoder->cmd_buffer, n_indices, 1, 0, 0, 0); -} - -void gpu_backend_end_frame() { - VkPresentInfoKHR present_info = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR }; - present_info.waitSemaphoreCount = 1; - present_info.pWaitSemaphores = &context.render_finished_semaphores[context.current_frame]; - - VkSwapchainKHR swapchains[] = { context.swapchain->handle }; - present_info.swapchainCount = 1; - present_info.pSwapchains = swapchains; - present_info.pImageIndices = &context.current_img_index; - - VkResult result = vkQueuePresentKHR(context.device->present_queue, &present_info); - if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) { - ERROR("Queue present error. recreate swapchain"); - recreate_swapchain(context.swapchain); - return; - } else if (result != VK_SUCCESS) { - ERROR_EXIT("failed to present swapchain image"); - } - context.current_frame = (context.current_frame + 1) % MAX_FRAMES_IN_FLIGHT; - - /* vkDeviceWaitIdle(context.device->logical_device); */ -} - -// TODO: Move into better order in file -void gpu_queue_submit(gpu_cmd_buffer* buffer) { - VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; - - // Specify semaphore to wait on - VkSemaphore wait_semaphores[] = { context.image_available_semaphores[context.current_frame] }; - VkPipelineStageFlags wait_stages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; - - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = wait_semaphores; - submit_info.pWaitDstStageMask = wait_stages; - - // Specify semaphore to signal when finished executing buffer - VkSemaphore signal_semaphores[] = { context.render_finished_semaphores[context.current_frame] }; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = signal_semaphores; - - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &buffer->cmd_buffer; - - VK_CHECK(vkQueueSubmit(context.device->graphics_queue, 1, &submit_info, - context.in_flight_fences[context.current_frame])); -} - -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) { - 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; - } - - vkGetPhysicalDeviceProperties(out_device->physical_device, &out_device->properties); - vkGetPhysicalDeviceFeatures(out_device->physical_device, &out_device->features); - vkGetPhysicalDeviceMemoryProperties(out_device->physical_device, &out_device->memory); - - 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); - - vulkan_device_query_swapchain_support(device, context.surface, &context.swapchain_support); - - return indices.has_graphics && indices.has_present && context.swapchain_support.mode_count > 0 && - context.swapchain_support.format_count > 0; -} - -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 q_fam_i = 0; q_fam_i < queue_family_count; q_fam_i++) { - // Graphics queue - if (queue_families[q_fam_i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { - indices.graphics_family_index = q_fam_i; - indices.has_graphics = true; - } - - VkBool32 present_support = false; - vkGetPhysicalDeviceSurfaceSupportKHR(device, q_fam_i, context.surface, &present_support); - if (present_support && !indices.has_present) { - indices.present_family_index = q_fam_i; - indices.has_present = true; - } - } - - return indices; -} - -bool create_logical_device(gpu_device* out_device) { - queue_family_indices indices = find_queue_families(out_device->physical_device); - INFO(" %s | %s | %s | %s | %s", bool_str(indices.has_graphics), bool_str(indices.has_present), - bool_str(indices.has_compute), bool_str(indices.has_transfer), - out_device->properties.deviceName); - TRACE("Graphics Family queue index: %d", indices.graphics_family_index); - TRACE("Present Family queue index: %d", indices.present_family_index); - TRACE("Compute Family queue index: %d", indices.compute_family_index); - TRACE("Transfer Family queue index: %d", indices.transfer_family_index); - - // Queues - f32 prio_one = 1.0; - VkDeviceQueueCreateInfo queue_create_infos[1] = { 0 }; - queue_create_infos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_create_infos[0].queueFamilyIndex = indices.graphics_family_index; - queue_create_infos[0].queueCount = 1; - queue_create_infos[0].pQueuePriorities = &prio_one; - queue_create_infos[0].flags = 0; - queue_create_infos[0].pNext = 0; - - // queue_create_infos[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - // queue_create_infos[1].queueFamilyIndex = indices.present_family_index; - // queue_create_infos[1].queueCount = 1; - // queue_create_infos[1].pQueuePriorities = &prio_one; - // queue_create_infos[1].flags = 0; - // queue_create_infos[1].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_infos; - 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"); - - context.device->queue_family_indicies = indices; - - // Retrieve queue handles - vkGetDeviceQueue(context.device->logical_device, indices.graphics_family_index, 0, - &context.device->graphics_queue); - vkGetDeviceQueue(context.device->logical_device, indices.present_family_index, 0, - &context.device->present_queue); - - return true; -} - -VkShaderModule create_shader_module(str8 spirv) { - VkShaderModuleCreateInfo create_info = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO }; - create_info.codeSize = spirv.len; - create_info.pCode = (uint32_t*)spirv.buf; - - VkShaderModule shader_module; - VK_CHECK(vkCreateShaderModule(context.device->logical_device, &create_info, context.allocator, - &shader_module)); - - return shader_module; -} - -void create_descriptor_pools() {} - -void create_swapchain_framebuffers() { - WARN("Recreating framebuffers..."); - u32 image_count = context.swapchain->image_count; - context.swapchain_framebuffers = - arena_alloc(&context.swapchain->swapchain_arena, image_count * sizeof(VkFramebuffer)); - for (u32 i = 0; i < image_count; i++) { - VkImageView attachments[1] = { context.swapchain->image_views[i] }; - - VkFramebufferCreateInfo framebuffer_create_info = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO }; - framebuffer_create_info.attachmentCount = 1; - framebuffer_create_info.pAttachments = attachments; - - framebuffer_create_info.renderPass = - context.main_renderpass; // TODO: description.renderpass->handle; - framebuffer_create_info.width = context.swapchain->extent.width; - framebuffer_create_info.height = context.swapchain->extent.height; - framebuffer_create_info.layers = 1; - - VK_CHECK(vkCreateFramebuffer(context.device->logical_device, &framebuffer_create_info, - context.allocator, &context.swapchain_framebuffers[i])); - } -} - -void create_sync_objects() { - VkSemaphoreCreateInfo semaphore_info = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; - VkFenceCreateInfo fence_info = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO }; - fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; - - for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - VK_CHECK(vkCreateSemaphore(context.device->logical_device, &semaphore_info, context.allocator, - &context.image_available_semaphores[i]);); - VK_CHECK(vkCreateSemaphore(context.device->logical_device, &semaphore_info, context.allocator, - &context.render_finished_semaphores[i]);); - - VK_CHECK(vkCreateFence(context.device->logical_device, &fence_info, context.allocator, - &context.in_flight_fences[i])); - } -} - -static i32 find_memory_index(u32 type_filter, u32 property_flags) { - VkPhysicalDeviceMemoryProperties memory_properties; - vkGetPhysicalDeviceMemoryProperties(context.device->physical_device, &memory_properties); - - for (u32 i = 0; i < memory_properties.memoryTypeCount; ++i) { - // Check each memory type to see if its bit is set to 1. - if (type_filter & (1 << i) && - (memory_properties.memoryTypes[i].propertyFlags & property_flags) == property_flags) { - return i; - } - } - - WARN("Unable to find suitable memory type!"); - return -1; -} - -buffer_handle gpu_buffer_create(u64 size, gpu_buffer_type buf_type, gpu_buffer_flags flags, - const void* data) { - VkBufferCreateInfo buffer_info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; - buffer_info.size = size; - buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - - switch (buf_type) { - case CEL_BUFFER_DEFAULT: - buffer_info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - break; - case CEL_BUFFER_VERTEX: - buffer_info.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - break; - case CEL_BUFFER_INDEX: - buffer_info.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; - break; - case CEL_BUFFER_UNIFORM: - buffer_info.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - break; - case CEL_BUFFER_COUNT: - WARN("Incorrect gpu_buffer_type provided. using default"); - break; - } - - buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - // "allocating" the cpu-side buffer struct - /* gpu_buffer buffer; */ - /* buffer.size = size; */ - buffer_handle handle; - gpu_buffer* buffer = buffer_pool_alloc(&context.resource_pools->buffers, &handle); - buffer->size = size; - - VK_CHECK(vkCreateBuffer(context.device->logical_device, &buffer_info, context.allocator, - &buffer->handle)); - - VkMemoryRequirements requirements; - vkGetBufferMemoryRequirements(context.device->logical_device, buffer->handle, &requirements); - - // Just make them always need all of them for now - i32 memory_index = - find_memory_index(requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - - // Allocate the actual VRAM - VkMemoryAllocateInfo allocate_info = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; - allocate_info.allocationSize = requirements.size; - allocate_info.memoryTypeIndex = (u32)memory_index; - - vkAllocateMemory(context.device->logical_device, &allocate_info, context.allocator, - &buffer->memory); - vkBindBufferMemory(context.device->logical_device, buffer->handle, buffer->memory, 0); - - /* Now there are two options: - * 1. create CPU-accessible memory -> map memory -> memcpy -> unmap - * 2. use a staging buffer thats CPU-accessible and copy its contents to a - * GPU-only buffer - */ - - /* context.buffers[context.buffer_count] = buffer; */ - /* context.buffer_count++; */ - - if (data) { - TRACE("Upload data as part of buffer creation"); - if (flags & CEL_BUFFER_FLAG_CPU) { - // map memory -> copy data in -> unmap memory - buffer_upload_bytes(handle, (bytebuffer){ .buf = (u8*)data, .size = size }, 0, size); - } else if (flags & CEL_BUFFER_FLAG_GPU) { - TRACE("Uploading data to buffer using staging buffer"); - // Create a staging buffer - buffer_handle staging = gpu_buffer_create(size, buf_type, CEL_BUFFER_FLAG_CPU, NULL); - - // Copy data into it - buffer_upload_bytes(staging, (bytebuffer){ .buf = (u8*)data, .size = size }, 0, size); - - // Enqueue a copy from the staging buffer into the DEVICE_LOCAL buffer - gpu_cmd_encoder temp_encoder = gpu_cmd_encoder_create(); - gpu_cmd_encoder_begin(temp_encoder); - encode_buffer_copy(&temp_encoder, staging, 0, handle, 0, size); - gpu_cmd_buffer copy_cmd_buffer = gpu_cmd_encoder_finish(&temp_encoder); - - VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &temp_encoder.cmd_buffer; - vkQueueSubmit(context.device->graphics_queue, 1, &submit_info, VK_NULL_HANDLE); - - // Cleanup - vkQueueWaitIdle(context.device->graphics_queue); - gpu_cmd_encoder_destroy(&temp_encoder); - gpu_buffer_destroy(staging); - } - } - - return handle; -} - -void gpu_buffer_destroy(buffer_handle buffer) { - gpu_buffer* b = buffer_pool_get(&context.resource_pools->buffers, buffer); - vkDestroyBuffer(context.device->logical_device, b->handle, context.allocator); - vkFreeMemory(context.device->logical_device, b->memory, context.allocator); - buffer_pool_dealloc(&context.resource_pools->buffers, buffer); -} - -// Upload data to a -void buffer_upload_bytes(buffer_handle gpu_buf, bytebuffer cpu_buf, u64 offset, u64 size) { - gpu_buffer* buffer = buffer_pool_get(&context.resource_pools->buffers, gpu_buf); - void* data_ptr; - vkMapMemory(context.device->logical_device, buffer->memory, 0, size, 0, &data_ptr); - DEBUG("Uploading %d bytes to buffer", size); - memcpy(data_ptr, cpu_buf.buf, size); - vkUnmapMemory(context.device->logical_device, buffer->memory); -} - -void encode_buffer_copy(gpu_cmd_encoder* encoder, buffer_handle src, u64 src_offset, - buffer_handle dst, u64 dst_offset, u64 copy_size) { - VkBufferCopy copy_region; - copy_region.srcOffset = src_offset; - copy_region.dstOffset = dst_offset; - copy_region.size = copy_size; - - gpu_buffer* src_buf = buffer_pool_get(&context.resource_pools->buffers, src); - gpu_buffer* dst_buf = buffer_pool_get(&context.resource_pools->buffers, dst); - vkCmdCopyBuffer(encoder->cmd_buffer, src_buf->handle, dst_buf->handle, 1, ©_region); -} - -// one-shot command buffers -VkCommandBuffer vulkan_command_buffer_create_oneshot() { - VkCommandBufferAllocateInfo alloc_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; - alloc_info.commandPool = context.device->pool; - alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - alloc_info.commandBufferCount = 1; - alloc_info.pNext = 0; - - VkCommandBuffer cmd_buffer; - vkAllocateCommandBuffers(context.device->logical_device, &alloc_info, &cmd_buffer); - - VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; - begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - - vkBeginCommandBuffer(cmd_buffer, &begin_info); - - return cmd_buffer; -} - -void vulkan_command_buffer_finish_oneshot(VkCommandBuffer cmd_buffer) { - VK_CHECK(vkEndCommandBuffer(cmd_buffer)); - - // submit to queue - VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &cmd_buffer; - VK_CHECK(vkQueueSubmit(context.device->graphics_queue, 1, &submit_info, 0)); - VK_CHECK(vkQueueWaitIdle(context.device->graphics_queue)); - - vkFreeCommandBuffers(context.device->logical_device, context.device->pool, 1, &cmd_buffer); -} - -void copy_buffer_to_buffer_oneshot(buffer_handle src, u64 src_offset, buffer_handle dst, - u64 dst_offset, u64 copy_size) { - VkBufferCopy copy_region; - copy_region.srcOffset = src_offset; - copy_region.dstOffset = dst_offset; - copy_region.size = copy_size; - - gpu_buffer* src_buf = buffer_pool_get(&context.resource_pools->buffers, src); - gpu_buffer* dst_buf = buffer_pool_get(&context.resource_pools->buffers, dst); - VkCommandBuffer temp_cmd_buffer = vulkan_command_buffer_create_oneshot(); - vkCmdCopyBuffer(temp_cmd_buffer, src_buf->handle, dst_buf->handle, 1, ©_region); - vulkan_command_buffer_finish_oneshot(temp_cmd_buffer); -} - -void copy_buffer_to_image_oneshot(buffer_handle src, texture_handle dst) { - gpu_buffer* src_buf = buffer_pool_get(&context.resource_pools->buffers, src); - gpu_texture* dst_tex = texture_pool_get(&context.resource_pools->textures, dst); - - VkCommandBuffer temp_cmd_buffer = vulkan_command_buffer_create_oneshot(); - - VkBufferImageCopy region; - region.bufferOffset = 0; - region.bufferRowLength = 0; - region.bufferImageHeight = 0; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.mipLevel = 0; - region.imageSubresource.baseArrayLayer = 0; - region.imageSubresource.layerCount = 1; - printf("Image details width: %d height %d\n", dst_tex->desc.extents.x, dst_tex->desc.extents.y); - region.imageOffset.x = 0; - region.imageOffset.y = 0; - region.imageOffset.z = 0; - region.imageExtent.width = dst_tex->desc.extents.x; - region.imageExtent.height = dst_tex->desc.extents.y; - region.imageExtent.depth = 1; - - vkCmdCopyBufferToImage(temp_cmd_buffer, src_buf->handle, dst_tex->handle, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - - vulkan_command_buffer_finish_oneshot(temp_cmd_buffer); -} - -VkImage vulkan_image_create(u32x2 dimensions, VkImageType image_type, VkFormat format, - VkImageUsageFlags usage) { - VkImage image; - - VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.extent.width = dimensions.x; - image_create_info.extent.height = dimensions.y; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.format = format; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_create_info.usage = usage; // VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - - VK_CHECK( - vkCreateImage(context.device->logical_device, &image_create_info, context.allocator, &image)); - - return image; -} - -texture_handle gpu_texture_create(texture_desc desc, bool create_view, const void* data) { - VkDeviceSize image_size = desc.extents.x * desc.extents.y * 4; - // FIXME: handle this properly - VkFormat format = desc.format == CEL_TEXTURE_FORMAT_8_8_8_8_RGBA_UNORM ? VK_FORMAT_R8G8B8A8_SRGB - : VK_FORMAT_D32_SFLOAT; - - VkImage image; // vulkan_image_create(desc.extents, VK_IMAGE_TYPE_2D, format, - // VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); - VkDeviceMemory image_memory; - - VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.extent.width = desc.extents.x; - image_create_info.extent.height = desc.extents.y; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.format = format; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - if (format == VK_FORMAT_D32_SFLOAT) { - image_create_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - } - image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - - VK_CHECK( - vkCreateImage(context.device->logical_device, &image_create_info, context.allocator, &image)); - - VkMemoryRequirements memory_reqs; - vkGetImageMemoryRequirements(context.device->logical_device, image, &memory_reqs); - - VkMemoryAllocateInfo alloc_info = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; - alloc_info.allocationSize = memory_reqs.size; - alloc_info.memoryTypeIndex = - find_memory_index(memory_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - vkAllocateMemory(context.device->logical_device, &alloc_info, context.allocator, &image_memory); - - vkBindImageMemory(context.device->logical_device, image, image_memory, 0); - - texture_handle handle; - gpu_texture* texture = texture_pool_alloc(&context.resource_pools->textures, &handle); - DEBUG("Allocated texture with handle %d", handle.raw); - texture->handle = image; - texture->debug_label = "Test Texture"; - texture->desc = desc; - texture->memory = image_memory; - texture->size = image_size; - - if (data) { - TRACE("Uploading pixel data to texture using staging buffer"); - // Create a staging buffer - buffer_handle staging = - gpu_buffer_create(image_size, CEL_BUFFER_DEFAULT, CEL_BUFFER_FLAG_CPU, NULL); - // Copy data into it - vulkan_transition_image_layout(texture, format, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - buffer_upload_bytes(staging, (bytebuffer){ .buf = (u8*)data, .size = image_size }, 0, - image_size); - copy_buffer_to_image_oneshot(staging, handle); - vulkan_transition_image_layout(texture, format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - gpu_buffer_destroy(staging); - } - - // Texture View - if (create_view) { - VkImageViewCreateInfo view_create_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; - view_create_info.image = image; - view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - view_create_info.format = format; - view_create_info.subresourceRange.aspectMask = - format == VK_FORMAT_D32_SFLOAT ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; - - view_create_info.subresourceRange.baseMipLevel = 0; - view_create_info.subresourceRange.levelCount = 1; - view_create_info.subresourceRange.baseArrayLayer = 0; - view_create_info.subresourceRange.layerCount = 1; - - VK_CHECK(vkCreateImageView(context.device->logical_device, &view_create_info, context.allocator, - &texture->view)); - } - - // Sampler - VkSamplerCreateInfo sampler_info = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; - sampler_info.magFilter = VK_FILTER_LINEAR; - sampler_info.minFilter = VK_FILTER_LINEAR; - sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.anisotropyEnable = VK_TRUE; - sampler_info.maxAnisotropy = 16; - sampler_info.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; - sampler_info.unnormalizedCoordinates = VK_FALSE; - sampler_info.compareEnable = VK_FALSE; - sampler_info.compareOp = VK_COMPARE_OP_ALWAYS; - sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler_info.mipLodBias = 0.0; - sampler_info.minLod = 0.0; - sampler_info.maxLod = 0.0; - - VkResult res = vkCreateSampler(context.device->logical_device, &sampler_info, context.allocator, - &texture->sampler); - if (res != VK_SUCCESS) { - ERROR("Error creating texture sampler for image %s", texture->debug_label); - exit(1); - } - - return handle; -} - -void vulkan_transition_image_layout(gpu_texture* texture, VkFormat format, VkImageLayout old_layout, - VkImageLayout new_layout) { - VkCommandBuffer temp_cmd_buffer = vulkan_command_buffer_create_oneshot(); - - VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; - barrier.oldLayout = old_layout; - barrier.newLayout = new_layout; - barrier.srcQueueFamilyIndex = context.device->queue_family_indicies.graphics_family_index; - barrier.dstQueueFamilyIndex = context.device->queue_family_indicies.graphics_family_index; - barrier.image = texture->handle; - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = 1; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - barrier.srcAccessMask = 0; // TODO - barrier.dstAccessMask = 0; // TODO - - VkPipelineStageFlags source_stage; - VkPipelineStageFlags dest_stage; - - if (old_layout == VK_IMAGE_LAYOUT_UNDEFINED && - new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { - barrier.srcAccessMask = 0; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - - source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - dest_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; - - } else if (old_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && - new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; - dest_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - } else { - FATAL("Unsupported image layout transition"); - return; - } - - vkCmdPipelineBarrier(temp_cmd_buffer, source_stage, dest_stage, 0, 0, 0, 0, 0, 1, &barrier); - - vulkan_command_buffer_finish_oneshot(temp_cmd_buffer); -} - -/* TYPED_POOL(gpu_buffer, buffer); */ -/* TYPED_POOL(gpu_texture, texture); */ - -/* void resource_pools_init(arena* a, struct resource_pools* res_pools) { */ -/* buffer_pool buf_pool = buffer_pool_create(a, MAX_BUFFERS, sizeof(gpu_buffer)); */ -/* res_pools->buffers = buf_pool; */ -/* texture_pool tex_pool = texture_pool_create(a, MAX_TEXTURES, sizeof(gpu_texture)); */ -/* res_pools->textures = tex_pool; */ - -/* context.resource_pools = res_pools; */ -/* } */ - -#endif diff --git a/src/render/archive/backends/vulkan/backend_vulkan.h b/src/render/archive/backends/vulkan/backend_vulkan.h deleted file mode 100644 index 6ca0bb5..0000000 --- a/src/render/archive/backends/vulkan/backend_vulkan.h +++ /dev/null @@ -1,118 +0,0 @@ -#pragma once -#include "defines.h" -#if defined(CEL_REND_BACKEND_VULKAN) -#include <vulkan/vk_platform.h> -#include <vulkan/vulkan.h> -#include <vulkan/vulkan_core.h> - -#include "mem.h" -#include "ral.h" -#include "ral_types.h" - -#define MAX_FRAMES_IN_FLIGHT 2 -#define GPU_SWAPCHAIN_IMG_COUNT 2 - -/* -Conventions: - - Place the 'handle' as the first field of a struct - - Vulkan specific data goes at the top, followed by our internal data -*/ - -typedef struct queue_family_indices { - u32 graphics_family_index; - u32 present_family_index; - u32 compute_family_index; - u32 transfer_family_index; - bool has_graphics; - bool has_present; - bool has_compute; - bool has_transfer; -} queue_family_indices; - -// typedef struct vulkan_framebuffer { -// } vulkan_framebuffer; - -typedef struct gpu_swapchain { - VkSwapchainKHR handle; - arena swapchain_arena; - VkExtent2D extent; - u32x2 dimensions; - VkSurfaceFormatKHR image_format; - VkPresentModeKHR present_mode; - u32 image_count; - VkImage* images; - VkImageView* image_views; -} gpu_swapchain; - -typedef struct gpu_device { - // In Vulkan we store both physical and logical device here - VkPhysicalDevice physical_device; - VkDevice logical_device; - VkPhysicalDeviceProperties properties; - VkPhysicalDeviceFeatures features; - VkPhysicalDeviceMemoryProperties memory; - queue_family_indices queue_family_indicies; - VkQueue graphics_queue; - VkQueue present_queue; - VkQueue compute_queue; - VkQueue transfer_queue; - VkCommandPool pool; -} gpu_device; - -typedef struct gpu_pipeline_layout { - VkPipelineLayout handle; -} gpu_pipeline_layout; - -typedef struct desc_set_uniform_buffer { - VkBuffer buffers[MAX_FRAMES_IN_FLIGHT]; - VkDeviceMemory uniform_buf_memorys[MAX_FRAMES_IN_FLIGHT]; - void* uniform_buf_mem_mappings[MAX_FRAMES_IN_FLIGHT]; - size_t size; -} desc_set_uniform_buffer; - -typedef struct gpu_pipeline { - VkPipeline handle; - VkPipelineLayout layout_handle; - - // Descriptor gubbins - shader_data data_layouts[MAX_SHADER_DATA_LAYOUTS]; - u32 data_layouts_count; - - VkDescriptorSetLayout* desc_set_layouts; - // Based on group, we know which data to load - desc_set_uniform_buffer* uniform_pointers; - u32 desc_set_layouts_count; - -} gpu_pipeline; - -typedef struct gpu_renderpass { - VkRenderPass handle; - // TODO: Where to store framebuffers? VkFramebuffer framebuffers[GPU_SWAPCHAIN_IMG_COUNT]; -} gpu_renderpass; - -typedef struct gpu_cmd_encoder { - VkCommandBuffer cmd_buffer; - VkDescriptorPool descriptor_pool; - gpu_pipeline* pipeline; -} gpu_cmd_encoder; - -typedef struct gpu_cmd_buffer { - VkCommandBuffer cmd_buffer; -} gpu_cmd_buffer; - -typedef struct gpu_buffer { - VkBuffer handle; - VkDeviceMemory memory; - u64 size; -} gpu_buffer; - -typedef struct gpu_texture { - VkImage handle; - VkDeviceMemory memory; - u64 size; - texture_desc desc; - VkImageView view; - VkSampler sampler; - char* debug_label; -} gpu_texture; -#endif
\ No newline at end of file diff --git a/src/render/immdraw.c b/src/render/immdraw.c deleted file mode 100644 index 8a10c65..0000000 --- a/src/render/immdraw.c +++ /dev/null @@ -1,176 +0,0 @@ -#include "immdraw.h" -#include "core.h" -#include "file.h" -#include "log.h" -#include "maths.h" -#include "maths_types.h" -#include "primitives.h" -#include "ral_common.h" -#include "ral_impl.h" -#include "ral_types.h" -#include "render.h" -#include "render_types.h" -#include "shader_layouts.h" - -void Immdraw_Init(Immdraw_Storage* storage) { - INFO("Immediate drawing initialisation"); - - // Meshes - Geometry sphere_geo = Geo_CreateUVsphere(1.0, 16, 16); - storage->sphere = Mesh_Create(&sphere_geo, true); - - Geometry cube_geo = Geo_CreateCuboid(f32x3(1.0, 1.0, 1.0)); - storage->cube = Mesh_Create(&cube_geo, true); - - Geometry plane_geo = Geo_CreatePlane(f32x2(1.0, 1.0), 1, 1); - storage->plane = Mesh_Create(&plane_geo, true); - - Geometry cone_geo = Geo_CreateCone(1.0, 1.0, 8); - storage->cone = Mesh_Create(&cone_geo, true); - - Geometry cyl_geo = Geo_CreateCylinder(1.0, 2.0, 8); - storage->cylinder = Mesh_Create(&cyl_geo, true); - - storage->bbox = GenBboxMesh(); - - // Pipeline / material - VertexDescription vertex_desc = { - .debug_label = "Immdraw Vertex", - .use_full_vertex_size = true, - }; - VertexDesc_AddAttr(&vertex_desc, "position", ATTR_F32x3); - VertexDesc_AddAttr(&vertex_desc, "normal", ATTR_F32x3); - - const char* vert_path = "assets/shaders/immdraw.vert"; - const char* frag_path = "assets/shaders/immdraw.frag"; - const char* vert_shader = string_from_file(vert_path); - const char* frag_shader = string_from_file(frag_path); - - ShaderDataLayout camera_data = Binding_Camera_GetLayout(NULL); - ShaderDataLayout imm_uniform_data = ImmediateUniforms_GetLayout(NULL); - - GraphicsPipelineDesc pipeline_desc = { - .debug_name = "Immediate Draw Pipeline", - .vertex_desc = static_3d_vertex_description(), - .data_layouts = { camera_data, imm_uniform_data }, - .data_layouts_count = 2, - .vs = { .debug_name = "Immdraw Vertex Shader", .filepath = vert_path, .code = vert_shader }, - .fs = { .debug_name = "Immdraw Fragment Shader", .filepath = frag_path, .code = frag_shader }, - .depth_test = true, - .wireframe = true, - }; - GPU_Renderpass* rpass = - GPU_Renderpass_Create((GPU_RenderpassDesc){ .default_framebuffer = true }); - storage->colour_pipeline = GPU_GraphicsPipeline_Create(pipeline_desc, rpass); -} - -void Immdraw_Shutdown(Immdraw_Storage* storage) { - GraphicsPipeline_Destroy(storage->colour_pipeline); -} - -void Immdraw_Sphere(Transform tf, Vec4 colour, bool wireframe) { - TRACE("Draw sphere"); - Immdraw_Storage* imm = Render_GetImmdrawStorage(); - Immdraw_Primitive(tf, CEL_TRI, 1.0, colour, wireframe, imm->sphere); -} -void Immdraw_Cuboid(Transform tf, Vec4 colour, bool wireframe) { - TRACE("Draw cube"); - Immdraw_Storage* imm = Render_GetImmdrawStorage(); - Immdraw_Primitive(tf, CEL_TRI, 1.0, colour, wireframe, imm->cube); -} -void Immdraw_Plane(Transform tf, Vec4 colour, bool wireframe) { - TRACE("Draw plane"); - Immdraw_Storage* imm = Render_GetImmdrawStorage(); - Immdraw_Primitive(tf, CEL_TRI, 1.0, colour, wireframe, imm->plane); -} - -void Immdraw_Bbox(Transform tf, Vec4 colour, bool wireframe) { - TRACE("Draw bbox"); - Immdraw_Storage* imm = Render_GetImmdrawStorage(); - Immdraw_Primitive(tf, CEL_LINE, 1.0, colour, wireframe, imm->bbox); -} - -void Immdraw_Cylinder(Transform tf, Vec4 colour, bool wireframe) { - TRACE("Draw cylinder"); - Immdraw_Storage* imm = Render_GetImmdrawStorage(); - Immdraw_Primitive(tf, CEL_TRI, 1.0, colour, wireframe, imm->cylinder); -} - -void Immdraw_Cone(Transform tf, Vec4 colour, bool wireframe) { - TRACE("Draw cone"); - Immdraw_Storage* imm = Render_GetImmdrawStorage(); - Immdraw_Primitive(tf, CEL_TRI, 1.0, colour, wireframe, imm->cone); -} - -void Immdraw_Primitive(Transform tf, PrimitiveTopology topology, f32 size, Vec4 colour, - bool wireframe, Mesh mesh) { - Immdraw_Storage* imm = Render_GetImmdrawStorage(); - GPU_CmdEncoder* enc = GPU_GetDefaultEncoder(); - - // begin renderpass - GPU_CmdEncoder_BeginRender(enc, imm->colour_pipeline->renderpass); - // bind pipeline - GPU_EncodeBindPipeline(enc, imm->colour_pipeline); - - // TODO: implement wireframe in other apis -#if defined(CEL_REND_BACKEND_OPENGL) -#include <glad/glad.h> - if (wireframe) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - } else { - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } -#endif - - // update uniforms - ImmediateUniforms uniforms = { - .model = transform_to_mat(&tf), - .colour = colour, - }; - Mat4 view, proj; - u32x2 dimensions = GPU_Swapchain_GetDimensions(); - RenderScene* scene = Render_GetScene(); - Camera_ViewProj(&scene->camera, (f32)dimensions.x, (f32)dimensions.y, &view, &proj); - Binding_Camera camera_data = { .view = view, - .projection = proj, - .viewPos = vec4(scene->camera.position.x, scene->camera.position.y, - scene->camera.position.z, 1.0) }; - GPU_EncodeBindShaderData(enc, 0, Binding_Camera_GetLayout(&camera_data)); - GPU_EncodeBindShaderData(enc, 1, ImmediateUniforms_GetLayout(&uniforms)); - - // draw call - GPU_EncodeSetVertexBuffer(enc, mesh.vertex_buffer); - GPU_EncodeSetIndexBuffer(enc, mesh.index_buffer); - GPU_EncodeDrawIndexed(enc, topology, mesh.geometry.index_count); - - // end renderpass - GPU_CmdEncoder_EndRender(enc); -} - -Mesh GenBboxMesh() { - Vertex_darray* vertices = Vertex_darray_new(8); - u32_darray* indices = u32_darray_new(24); - - // normals & uvs dont matter - VERT_3D(vertices, FRONT_BOT_LEFT, VEC3_NEG_Z, vec2(0, 0)); - VERT_3D(vertices, FRONT_BOT_RIGHT, VEC3_NEG_Z, vec2(0, 0)); - VERT_3D(vertices, BACK_BOT_LEFT, VEC3_NEG_Z, vec2(0, 0)); - VERT_3D(vertices, BACK_BOT_RIGHT, VEC3_NEG_Z, vec2(0, 0)); - VERT_3D(vertices, FRONT_TOP_LEFT, VEC3_NEG_Z, vec2(0, 0)); - VERT_3D(vertices, FRONT_TOP_RIGHT, VEC3_NEG_Z, vec2(0, 0)); - VERT_3D(vertices, BACK_TOP_LEFT, VEC3_NEG_Z, vec2(0, 0)); - VERT_3D(vertices, BACK_TOP_RIGHT, VEC3_NEG_Z, vec2(0, 0)); - - u32 line_indices[24] = { 0, 1, 2, 3, 0, 2, 1, 3, 4, 5, 6, 7, 4, 6, 5, 7, 0, 4, 1, 5, 2, 6, 3, 7 }; - for (u32 i = 0; i < 24; i++) { - u32_darray_push(indices, line_indices[i]); - } - - Geometry geo = { .format = VERTEX_STATIC_3D, - .has_indices = true, - .index_count = indices->len, - .vertices = vertices, - .indices = indices }; - - return Mesh_Create(&geo, true); -} diff --git a/src/render/immdraw.h b/src/render/immdraw.h deleted file mode 100644 index 2911350..0000000 --- a/src/render/immdraw.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @brief Immediate-mode drawing APIs - */ - -#pragma once -#include "defines.h" -#include "maths_types.h" -#include "ral_impl.h" -#include "ral_types.h" -#include "render_types.h" - -typedef struct Immdraw_Storage { - Mesh plane; - Mesh cube; - Mesh sphere; - Mesh cylinder; - Mesh cone; - Mesh bbox; - GPU_Pipeline* colour_pipeline; /** @brief Pipeline for drawing geometry that has vertex colours */ -} Immdraw_Storage; - -typedef struct ImmediateUniforms { - Mat4 model; - Vec4 colour; -} ImmediateUniforms; - -// --- Public API - -PUB void Immdraw_Init(Immdraw_Storage* storage); -PUB void Immdraw_Shutdown(Immdraw_Storage* storage); - -// These functions cause a pipeline switch and so aren't optimised for performance -PUB void Immdraw_Plane(Transform tf, Vec4 colour, bool wireframe); -PUB void Immdraw_Cuboid(Transform tf, Vec4 colour, bool wireframe); -PUB void Immdraw_Cylinder(Transform tf, Vec4 colour, bool wireframe); -PUB void Immdraw_Cone(Transform tf, Vec4 colour, bool wireframe); -PUB void Immdraw_Sphere(Transform tf, Vec4 colour, bool wireframe); -PUB void Immdraw_Bbox(Transform tf, Vec4 colour, bool wireframe); - -PUB void Immdraw_TransformGizmo(Transform tf, f32 size); - -// --- Internal - -void Immdraw_Primitive(Transform tf, PrimitiveTopology topology, f32 size, Vec4 colour, - bool wireframe, Mesh mesh); - -Mesh GenBboxMesh(); - -static ShaderDataLayout ImmediateUniforms_GetLayout(void* data) { - ImmediateUniforms* d = (ImmediateUniforms*)data; - bool has_data = data != NULL; - - ShaderBinding b1 = { .label = "ImmUniforms", - .kind = BINDING_BYTES, - // .vis = VISIBILITY_VERTEX, - .data.bytes.size = sizeof(ImmediateUniforms) }; - - if (has_data) { - b1.data.bytes.data = d; - } - - return (ShaderDataLayout){ .bindings = { b1 }, .binding_count = 1 }; -} diff --git a/src/render/pbr.c b/src/render/pbr.c deleted file mode 100644 index 4bad528..0000000 --- a/src/render/pbr.c +++ /dev/null @@ -1,266 +0,0 @@ -#include "pbr.h" -#include "animation.h" -#include "camera.h" -#include "core.h" -#include "file.h" -#include "log.h" -#include "maths.h" -#include "mem.h" -#include "ral_common.h" -#include "ral_impl.h" -#include "ral_types.h" -#include "render.h" -#include "render_types.h" -#include "shader_layouts.h" - -void PBR_Init(PBR_Storage* storage) { - INFO("PBR shaders init"); - storage->pbr_pass = PBR_RPassCreate(); - PBR_PipelinesCreate(storage, storage->pbr_pass); -} - -GPU_Renderpass* PBR_RPassCreate() { - GPU_RenderpassDesc desc = { .default_framebuffer = true }; - return GPU_Renderpass_Create(desc); -} - -void PBR_PipelinesCreate(PBR_Storage* storage, GPU_Renderpass* rpass) { - // Common shader bindings - ShaderDataLayout camera_data = Binding_Camera_GetLayout(NULL); - ShaderDataLayout model_data = Binding_Model_GetLayout(NULL); - ShaderDataLayout material_data = PBRMaterial_GetLayout(NULL); - ShaderDataLayout lights_data = Binding_Lights_GetLayout(NULL); - - // Static - { - const char* vert_path = "assets/shaders/static_geometry.vert"; - const char* frag_path = "assets/shaders/pbr_textured.frag"; - char* vert_shader = string_from_file(vert_path); - char* frag_shader = string_from_file(frag_path); - - GraphicsPipelineDesc desc = { - .debug_name = "PBR (Static) Pipeline", - .vertex_desc = static_3d_vertex_description(), - .data_layouts = { camera_data, model_data, material_data, lights_data }, - .data_layouts_count = 4, - .vs = { .debug_name = "PBR (textured) Vertex Shader", - .filepath = str8(vert_path), - .code = vert_shader }, - .fs = { .debug_name = "PBR (textured) Fragment Shader", - .filepath = str8(frag_path), - .code = frag_shader }, - .depth_test = true, - .wireframe = true, - }; - storage->pbr_static_pipeline = GPU_GraphicsPipeline_Create(desc, rpass); - } - - // Skinned - { - const char* vert_path = "assets/shaders/skinned_geometry.vert"; - const char* frag_path = "assets/shaders/pbr_textured.frag"; - char* vert_shader = string_from_file(vert_path); - char* frag_shader = string_from_file(frag_path); - - ShaderDataLayout anim_uniform = AnimData_GetLayout(NULL); - - VertexDescription vertex_desc = { .debug_label = "Skinned vertices", - .use_full_vertex_size = true }; - VertexDesc_AddAttr(&vertex_desc, "inPosition", ATTR_F32x3); - VertexDesc_AddAttr(&vertex_desc, "inNormal", ATTR_F32x3); - VertexDesc_AddAttr(&vertex_desc, "inTexCoords", ATTR_F32x2); - VertexDesc_AddAttr(&vertex_desc, "inBoneIndices", ATTR_I32x4); - VertexDesc_AddAttr(&vertex_desc, "inWeights", ATTR_F32x4); - - GraphicsPipelineDesc desc = { - .debug_name = "PBR (Skinned) Pipeline", - .vertex_desc = vertex_desc, - .data_layouts = { camera_data, model_data, material_data, lights_data, anim_uniform }, - .data_layouts_count = 5, - .vs = { .debug_name = "PBR (textured) Vertex Shader", - .filepath = str8(vert_path), - .code = vert_shader }, - .fs = { .debug_name = "PBR (textured) Fragment Shader", - .filepath = str8(frag_path), - .code = frag_shader }, - .depth_test = true, - .wireframe = true, - }; - storage->pbr_skinned_pipeline = GPU_GraphicsPipeline_Create(desc, rpass); - } -} - -void PBR_Execute(PBR_Storage* storage, Camera camera, TextureHandle shadowmap_tex, - RenderEnt* entities, size_t entity_count) { - // 1. set up our pipeline - // 2. upload constant data (camera, lights) - // 3. draw each entity - // - upload material data -> in the future we will sort & batch by material - // - upload model transform - // - emit draw call - - GPU_CmdEncoder* enc = GPU_GetDefaultEncoder(); - GPU_CmdEncoder_BeginRender(enc, storage->pbr_pass); - - // TEMP: only do skinned - GPU_EncodeBindPipeline(enc, storage->pbr_skinned_pipeline); - - // Feed shader data - Mat4 view, proj; - u32x2 dimensions = GPU_Swapchain_GetDimensions(); - Camera_ViewProj(&camera, (f32)dimensions.x, (f32)dimensions.y, &view, &proj); - Binding_Camera camera_data = { .view = view, - .projection = proj, - .viewPos = vec4(camera.position.x, camera.position.y, - camera.position.z, 1.0) }; - GPU_EncodeBindShaderData(enc, 0, Binding_Camera_GetLayout(&camera_data)); - - Vec3 light_color = vec3(300.0, 300.0, 300.0); - Binding_Lights - lights_data = { .pointLights = { - // FIXME: add lights to our RenderScene structure. for now these are - // hardcoded - (pbr_point_light){ .pos = vec3(0.0, 6.0, 6.0), .color = light_color }, - (pbr_point_light){ .pos = vec3(-10, 10, 10), .color = light_color }, - (pbr_point_light){ .pos = vec3(10, -10, 10), .color = light_color }, - (pbr_point_light){ .pos = vec3(-10, -10, 10), .color = light_color }, - } }; - GPU_EncodeBindShaderData(enc, 3, Binding_Lights_GetLayout(&lights_data)); - - // TODO: Add shadowmap texture to uniforms - Mesh_pool* mesh_pool = Render_GetMeshPool(); - Material_pool* material_pool = Render_GetMaterialPool(); - - for (size_t ent_i = 0; ent_i < entity_count; ent_i++) { - RenderEnt renderable = entities[ent_i]; - Mesh* mesh = Mesh_pool_get(mesh_pool, renderable.mesh); - Material* mat = Material_pool_get(material_pool, renderable.material); - - // upload material data - PBRMaterialUniforms material_data = { .mat = *mat }; - GPU_EncodeBindShaderData(enc, 2, PBRMaterial_GetLayout(&material_data)); - - // upload model transform - Binding_Model model_data = { .model = renderable.affine }; - GPU_EncodeBindShaderData(enc, 1, Binding_Model_GetLayout(&model_data)); - - // Skinning matrices - - // 1. calculate matrices - AnimDataUniform anim_data = { 0 }; - CASSERT(renderable.armature); - Armature* skeleton = renderable.armature; - // Skip the first one as we assume its root for this test - for (int j_i = 1; j_i < skeleton->joints->len; j_i++) { - Joint* j = &skeleton->joints->data[j_i]; - j->local_transform = transform_to_mat(&j->transform_components); - Mat4 m = mat4_mult(j->local_transform, j->inverse_bind_matrix); - Joint* p = &skeleton->joints->data[j->parent]; - j->local_transform = mat4_mult(j->local_transform, p->local_transform); - printf("Quat %f \n", j->transform_components.rotation.z); - } - - // 2. bind and upload - for (int j_i = 1; j_i < skeleton->joints->len; j_i++) { - anim_data.bone_matrices[j_i] = skeleton->joints->data[j_i].local_transform; - } - GPU_EncodeBindShaderData(enc, 3, AnimData_GetLayout(&anim_data)); - - // set buffers - GPU_EncodeSetVertexBuffer(enc, mesh->vertex_buffer); - GPU_EncodeSetIndexBuffer(enc, mesh->index_buffer); - // draw - GPU_EncodeDrawIndexedTris(enc, mesh->geometry.index_count); - } - - GPU_CmdEncoder_EndRender(enc); -} - -void PBRMaterial_BindData(ShaderDataLayout* layout, const void* data) { - PBRMaterialUniforms* d = (PBRMaterialUniforms*)data; - CASSERT(data); - CASSERT(layout->binding_count == 5); - - TextureHandle white1x1 = Render_GetWhiteTexture(); - if (d->mat.albedo_map.raw != INVALID_TEX_HANDLE.raw) { - layout->bindings[0].data.texture.handle = d->mat.albedo_map; - } else { - layout->bindings[0].data.texture.handle = white1x1; - } - // TODO .. the rest -} - -ShaderDataLayout PBRMaterial_GetLayout(void* data) { - PBRMaterialUniforms* d = (PBRMaterialUniforms*)data; - bool has_data = data != NULL; - - ShaderBinding b1 = { - .label = "albedoMap", - .kind = BINDING_TEXTURE, - }; - ShaderBinding b2 = { - .label = "metallicRoughnessMap", - .kind = BINDING_TEXTURE, - }; - ShaderBinding b3 = { - .label = "aoMap", - .kind = BINDING_TEXTURE, - }; - ShaderBinding b4 = { - .label = "normalMap", - .kind = BINDING_TEXTURE, - }; - ShaderBinding b5 = { .label = "PBR_Params", - .kind = BINDING_BYTES, - .data.bytes.size = sizeof(PBR_Params) }; - - if (has_data) { - TextureHandle white1x1 = Render_GetWhiteTexture(); - if (d->mat.albedo_map.raw != INVALID_TEX_HANDLE.raw) { - b1.data.texture.handle = d->mat.albedo_map; - } else { - b1.data.texture.handle = white1x1; - } - - if (d->mat.metallic_roughness_map.raw != INVALID_TEX_HANDLE.raw) { - b2.data.texture.handle = d->mat.metallic_roughness_map; - } else { - b2.data.texture.handle = white1x1; - } - - if (d->mat.ambient_occlusion_map.raw != INVALID_TEX_HANDLE.raw) { - b3.data.texture.handle = d->mat.ambient_occlusion_map; - } else { - b3.data.texture.handle = white1x1; - } - - if (d->mat.normal_map.raw != INVALID_TEX_HANDLE.raw) { - b4.data.texture.handle = d->mat.normal_map; - } else { - b4.data.texture.handle = white1x1; - } - - arena* frame = Render_GetFrameArena(); - PBR_Params* params = arena_alloc(frame, sizeof(PBR_Params)); - params->albedo = d->mat.base_colour; - params->metallic = d->mat.metallic; - params->roughness = d->mat.roughness; - params->ambient_occlusion = d->mat.ambient_occlusion; - b5.data.bytes.data = params; - } - - return (ShaderDataLayout){ .bindings = { b1, b2, b3, b4, b5 }, .binding_count = 5 }; -} - -Material PBRMaterialDefault() { - return (Material){ .name = "Standard Material", - .kind = MAT_PBR, - .base_colour = vec3(1.0, 1.0, 1.0), - .metallic = 0.0, - .roughness = 0.5, - .ambient_occlusion = 0.0, - .albedo_map = INVALID_TEX_HANDLE, - .metallic_roughness_map = INVALID_TEX_HANDLE, - .normal_map = INVALID_TEX_HANDLE, - .ambient_occlusion_map = INVALID_TEX_HANDLE }; -} diff --git a/src/render/pbr.h b/src/render/pbr.h deleted file mode 100644 index 5a21533..0000000 --- a/src/render/pbr.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @file pbr.h - * @brief PBR render pass and uniforms - */ - -#pragma once -#include "backend_opengl.h" -#include "camera.h" -#include "defines.h" -#include "maths_types.h" -#include "ral_types.h" -#include "render_types.h" - -// --- Public API - -/** @brief Holds data for the PBR pipeline */ -typedef struct PBR_Storage { - GPU_Renderpass* pbr_pass; - GPU_Pipeline* pbr_static_pipeline; - GPU_Pipeline* pbr_skinned_pipeline; -} PBR_Storage; - -typedef struct PBRMaterialUniforms { - Material mat; -} PBRMaterialUniforms; - -/** @brief */ -PUB void PBR_Init(PBR_Storage* storage); - -// NOTE: For simplicity's sake we will render this pass directly to the default framebuffer -// internally this defers to `PBR_Execute()` -PUB void PBR_Run(PBR_Storage* storage - // light data - // camera - // geometry - // materials -); - -/** @brief Parameters that get passed as a uniform block to the PBR shader */ -typedef struct PBR_Params { - Vec3 albedo; - f32 metallic; - f32 roughness; - f32 ambient_occlusion; -} PBR_Params; - -/** @brief Textures that will get passed into the PBR shader if they're not `INVALID_TEX_HANDLE` */ -typedef struct PBR_Textures { - TextureHandle albedo_map; - TextureHandle normal_map; - bool metal_roughness_combined; - TextureHandle metallic_map; - TextureHandle roughness_map; - TextureHandle ao_map; -} PBR_Textures; - -/** @brief Returns a default white matte material */ -PUB Material PBRMaterialDefault(); - -PUB ShaderDataLayout PBRMaterial_GetLayout(void* data); - -// --- Internal - -GPU_Renderpass* PBR_RPassCreate(); /** @brief Create the PBR Renderpass */ - -void PBR_PipelinesCreate(PBR_Storage* storage, - GPU_Renderpass* rpass); /** @brief Create PBR Pipelines */ - -void PBR_Execute(PBR_Storage* storage, Camera camera, TextureHandle shadowmap_tex, - RenderEnt* entities, size_t entity_count); diff --git a/src/render/render.c b/src/render/render.c deleted file mode 100644 index af636a8..0000000 --- a/src/render/render.c +++ /dev/null @@ -1,359 +0,0 @@ -/** - * @brief - */ - -#include "render.h" -#include <assert.h> -#include <glfw3.h> -#include <stdio.h> -#include "camera.h" -#include "core.h" -#include "grid.h" -#include "immdraw.h" -#include "log.h" -#include "maths.h" -#include "maths_types.h" -#include "mem.h" -#include "pbr.h" -#include "ral_common.h" -#include "ral_impl.h" -#include "ral_types.h" -#include "render_types.h" -#include "shadows.h" -#include "terrain.h" - -#define STB_IMAGE_IMPLEMENTATION -#include <stb_image.h> - -#define FRAME_ARENA_SIZE MB(1) -#define POOL_SIZE_BYTES \ - MB(10) // we will reserve 10 megabytes up front to store resource, mesh, and material pools -#define MAX_MESHES 1024 -#define MAX_MATERIALS 256 - -extern Core g_core; - -struct Renderer { - struct GLFWwindow* window; - RendererConfig config; - GPU_Device device; - GPU_Swapchain swapchain; - GPU_Renderpass* default_renderpass; - bool frame_aborted; - RenderMode render_mode; - RenderScene scene; - PBR_Storage* pbr; - Shadow_Storage* shadows; - Terrain_Storage* terrain; - Grid_Storage* grid; - Immdraw_Storage* immediate; - // Text_Storage* text; - ResourcePools* resource_pools; - Mesh_pool mesh_pool; - Material_pool material_pool; - arena frame_arena; - TextureHandle white_1x1; - TextureHandle black_1x1; -}; - -Renderer* get_renderer() { return g_core.renderer; } - -bool Renderer_Init(RendererConfig config, Renderer* ren, GLFWwindow** out_window, - GLFWwindow* optional_window) { - INFO("Renderer init"); - ren->render_mode = RENDER_MODE_DEFAULT; - - ren->frame_arena = arena_create(malloc(FRAME_ARENA_SIZE), FRAME_ARENA_SIZE); - - // init resource pools - DEBUG("Initialise GPU resource pools"); - arena pool_arena = arena_create(malloc(POOL_SIZE_BYTES), POOL_SIZE_BYTES); - ren->resource_pools = arena_alloc(&pool_arena, sizeof(struct ResourcePools)); - ResourcePools_Init(&pool_arena, ren->resource_pools); - ren->mesh_pool = Mesh_pool_create(&pool_arena, MAX_MESHES, sizeof(Mesh)); - ren->material_pool = Material_pool_create(&pool_arena, MAX_MATERIALS, sizeof(Material)); - - // GLFW window creation - GLFWwindow* window; - if (optional_window != NULL) { - INFO("GLFWwindow pointer was provided!!!! Skipping generic glfw init.."); - window = optional_window; - } else { - INFO("No GLFWwindow provided - creating one"); - // NOTE: all platforms use GLFW at the moment but thats subject to change - glfwInit(); - -#if defined(CEL_REND_BACKEND_OPENGL) - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); -#elif defined(CEL_REND_BACKEND_VULKAN) - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); -#endif - - window = glfwCreateWindow(config.scr_width, config.scr_height, config.window_name, NULL, NULL); - INFO("Window created"); - if (window == NULL) { - ERROR("Failed to create GLFW window\n"); - glfwTerminate(); - return false; - } - } - - ren->window = window; - *out_window = window; - - glfwMakeContextCurrent(ren->window); - - DEBUG("Set up GLFW window callbacks"); - glfwSetWindowSizeCallback(window, Render_WindowSizeChanged); - - // set the RAL backend up - if (!GPU_Backend_Init(config.window_name, window, ren->resource_pools)) { - return false; - } - - GPU_Device_Create(&ren->device); - GPU_Swapchain_Create(&ren->swapchain); - - // set up default scene - Camera default_cam = - Camera_Create(vec3(0.0, 2.0, 4.0), vec3_normalise(vec3(0.0, -2.0, -4.0)), VEC3_Y, 45.0); - SetCamera(default_cam); - DirectionalLight default_light = { /* TODO */ }; - SetMainLight(default_light); - - // create our renderpasses - ren->shadows = malloc(sizeof(Shadow_Storage)); - Shadow_Init(ren->shadows, 1024, 1024); - - ren->pbr = calloc(1, sizeof(PBR_Storage)); - PBR_Init(ren->pbr); - - ren->terrain = calloc(1, sizeof(Terrain_Storage)); - Terrain_Init(ren->terrain); - - // FIXME - // ren->grid = calloc(1, sizeof(Grid_Storage)); - // Grid_Init(ren->grid); - - ren->immediate = calloc(1, sizeof(Immdraw_Storage)); - Immdraw_Init(ren->immediate); - - // load default textures - ren->white_1x1 = TextureLoadFromFile("assets/textures/white1x1.png"); - ren->black_1x1 = TextureLoadFromFile("assets/textures/black1x1.png"); - - return true; -} - -void Renderer_Shutdown(Renderer* ren) { - free(ren->shadows); - DEBUG("Freed Shadows storage"); - free(ren->pbr); - DEBUG("Freed PBR storage"); - free(ren->terrain); - DEBUG("Freed Terrain storage"); - free(ren->immediate); - DEBUG("Freed Immdraw storage"); - arena_free_storage(&ren->frame_arena); - DEBUG("Freed frame allocator buffer"); -} -size_t Renderer_GetMemReqs() { return sizeof(Renderer); } - -void Render_WindowSizeChanged(GLFWwindow* window, i32 new_width, i32 new_height) { - (void)window; - INFO("Window size changed callback"); - // Renderer* ren = Core_GetRenderer(&g_core); - GPU_Swapchain_Resize(new_width, new_height); -} - -void Render_FrameBegin(Renderer* ren) { - arena_free_all(&ren->frame_arena); - ren->frame_aborted = false; - if (!GPU_Backend_BeginFrame()) { - ren->frame_aborted = true; - WARN("Frame aborted"); - return; - } -} -void Render_FrameEnd(Renderer* ren) { - if (ren->frame_aborted) { - return; - } - - GPU_CmdEncoder* enc = GPU_GetDefaultEncoder(); - - GPU_Backend_EndFrame(); -} -void Render_RenderEntities(RenderEnt* entities, size_t entity_count) { - Renderer* ren = get_renderer(); - RenderScene scene = ren->scene; - - // FUTURE: Depth pre-pass - - Shadow_Storage* shadow_storage = Render_GetShadowStorage(); - shadow_storage->enabled = false; - TextureHandle sun_shadowmap = - shadow_storage->enabled ? Shadow_GetShadowMapTexture(shadow_storage) : INVALID_TEX_HANDLE; - - PBR_Execute(ren->pbr, scene.camera, sun_shadowmap, entities, entity_count); -} - -TextureData TextureDataLoad(const char* path, bool invert_y) { - TRACE("Load texture %s", path); - - // load the file data - int width, height, num_channels; - stbi_set_flip_vertically_on_load(invert_y); - -#pragma GCC diagnostic ignored "-Wpointer-sign" - char* data = stbi_load(path, &width, &height, &num_channels, 0); - if (data) { - DEBUG("loaded texture: %s", path); - } else { - WARN("failed to load texture"); - } - - // printf("width: %d height: %d num channels: %d\n", width, height, num_channels); - - unsigned int channel_type; - GPU_TextureFormat format; - if (num_channels == 4) { - channel_type = GL_RGBA; - format = TEXTURE_FORMAT_8_8_8_8_RGBA_UNORM; - } else { - channel_type = GL_RGB; - format = TEXTURE_FORMAT_8_8_8_RGB_UNORM; - } - TextureDesc desc = { - .extents = { width, height }, - .format = format, - .num_channels = num_channels, - .tex_type = TEXTURE_TYPE_2D, - }; - - return (TextureData){ .description = desc, .image_data = data }; -} - -TextureHandle TextureLoadFromFile(const char* path) { - TextureData tex_data = TextureDataLoad(path, false); - TextureHandle h = GPU_TextureCreate(tex_data.description, true, tex_data.image_data); - return h; -} - -Mesh Mesh_Create(Geometry* geometry, bool free_on_upload) { - Mesh m = { 0 }; - - // Create and upload vertex buffer - size_t vert_bytes = geometry->vertices->len * sizeof(Vertex); - INFO("Creating vertex buffer with size %d (%d x %d)", vert_bytes, geometry->vertices->len, - sizeof(Vertex)); - m.vertex_buffer = - GPU_BufferCreate(vert_bytes, BUFFER_VERTEX, BUFFER_FLAG_GPU, geometry->vertices->data); - - // Create and upload index buffer - if (geometry->has_indices) { - size_t index_bytes = geometry->indices->len * sizeof(u32); - INFO("Creating index buffer with size %d (len: %d)", index_bytes, geometry->indices->len); - m.index_buffer = - GPU_BufferCreate(index_bytes, BUFFER_INDEX, BUFFER_FLAG_GPU, geometry->indices->data); - } - - m.is_uploaded = true; - m.geometry = *geometry; // clone geometry data and store on Mesh struct - if (free_on_upload) { - Geometry_Destroy(geometry); - } - return m; -} - -void Geometry_Destroy(Geometry* geometry) { - if (geometry->indices) { - u32_darray_free(geometry->indices); - } - if (geometry->vertices) { - Vertex_darray_free(geometry->vertices); - } -} -PUB MeshHandle Mesh_Insert(Mesh* mesh) { return Mesh_pool_insert(Render_GetMeshPool(), mesh); } -PUB MaterialHandle Material_Insert(Material* material) { - return Material_pool_insert(Render_GetMaterialPool(), material); -} -Mesh* Mesh_Get(MeshHandle handle) { return Mesh_pool_get(Render_GetMeshPool(), handle); } - -void Mesh_DebugPrint(Mesh* mesh) { - printf("Mesh %d vertices %d indices %d joints \n", mesh->geometry.vertices->len, - mesh->geometry.indices->len); -} - -size_t ModelExtractRenderEnts(RenderEnt_darray* entities, ModelHandle model_handle, Mat4 affine, - RenderEntityFlags flags) { - Model* model = MODEL_GET(model_handle); - for (u32 i = 0; i < model->mesh_count; i++) { - Mesh* m = Mesh_pool_get(Render_GetMeshPool(), model->meshes[i]); - RenderEnt data = { .mesh = model->meshes[i], - .material = m->material, - .affine = affine, - // .bounding_box - .flags = flags }; - RenderEnt_darray_push(entities, data); - } - return model->mesh_count; // how many RenderEnts we pushed -} - -void SetCamera(Camera camera) { g_core.renderer->scene.camera = camera; } -void SetMainLight(DirectionalLight light) { g_core.renderer->scene.sun = light; } - -arena* GetRenderFrameArena(Renderer* r) { return &r->frame_arena; } - -RenderScene* Render_GetScene() { - Renderer* ren = Core_GetRenderer(&g_core); - return &ren->scene; -} - -Shadow_Storage* Render_GetShadowStorage() { - Renderer* ren = Core_GetRenderer(&g_core); - return ren->shadows; -} - -Terrain_Storage* Render_GetTerrainStorage() { - Renderer* ren = Core_GetRenderer(&g_core); - return ren->terrain; -} - -Grid_Storage* Render_GetGridStorage() { - Renderer* ren = Core_GetRenderer(&g_core); - return ren->grid; -} - -Immdraw_Storage* Render_GetImmdrawStorage() { - Renderer* ren = Core_GetRenderer(&g_core); - return ren->immediate; -} - -TextureHandle Render_GetWhiteTexture() { - Renderer* ren = Core_GetRenderer(&g_core); - return ren->white_1x1; -} - -/** @return an arena allocator that gets cleared at the beginning of every render frame */ -arena* Render_GetFrameArena() { - Renderer* ren = Core_GetRenderer(&g_core); - return &ren->frame_arena; -} - -Mesh_pool* Render_GetMeshPool() { - Renderer* ren = Core_GetRenderer(&g_core); - return &ren->mesh_pool; -} -Material_pool* Render_GetMaterialPool() { - Renderer* ren = Core_GetRenderer(&g_core); - return &ren->material_pool; -} - -void Render_SetRenderMode(RenderMode mode) { - Renderer* ren = Core_GetRenderer(&g_core); - ren->render_mode = mode; -} diff --git a/src/render/render.h b/src/render/render.h deleted file mode 100644 index d752f8b..0000000 --- a/src/render/render.h +++ /dev/null @@ -1,151 +0,0 @@ -/** - * @brief - */ - -#pragma once -#include "camera.h" -#include "defines.h" -#include "grid.h" -#include "immdraw.h" -#include "maths_types.h" -#include "ral_types.h" -#include "render_types.h" -#include "shadows.h" - -typedef struct Renderer Renderer; -typedef struct GLFWwindow GLFWwindow; -typedef struct RendererConfig { - const char* window_name; - u32 scr_width, scr_height; - Vec3 clear_colour; -} RendererConfig; - -typedef struct RenderFlags { - bool wireframe; -} RenderFlags; - -typedef struct RenderCtx { - Mat4 view; - Mat4 projection; -} RenderCtx; - -/** @brief Holds globally bound data for rendering a scene. Typically held by the renderer. - * Whenever you call draw functions you can think of this as an implicit parameter. */ -typedef struct RenderScene { - Camera camera; - DirectionalLight sun; -} RenderScene; - -PUB void SetCamera(Camera camera); -PUB void SetMainLight(DirectionalLight light); - -// #define MESH_GET(h) (Mesh_pool_get(g_core.renderer->meshes, h)) -// #define MATERIAL_GET(h) (Material_pool_get(g_core.renderer->material, h)) - -// --- Lifecycle - -PUB bool Renderer_Init(RendererConfig config, Renderer* renderer, GLFWwindow** out_window, - GLFWwindow* optional_window); -PUB void Renderer_Shutdown(Renderer* renderer); -PUB size_t Renderer_GetMemReqs(); -void Render_WindowSizeChanged(GLFWwindow* window, i32 new_width, i32 new_height); - -// internal init functions -void DefaultPipelinesInit(Renderer* renderer); - -// NOTE: All of these functions grab the Renderer instance off the global Core -PUB void Render_FrameBegin(Renderer* renderer); -PUB void Render_FrameEnd(Renderer* renderer); - -/** @brief */ -PUB void Render_RenderEntities(RenderEnt* entities, size_t entity_count); - -// TODO: Render_FrameDraw(); - this will - -// --- Resources - -PUB TextureData TextureDataLoad(const char* path, bool invert_y); -PUB void TextureUpload(TextureHandle handle, size_t n_bytes, const void* data); -PUB TextureHandle TextureLoadFromFile(const char* path); -PUB ModelHandle ModelLoad(const char* debug_name, const char* filepath); - -// --- Rendering Data - -PUB Mesh Mesh_Create(Geometry* geometry, bool free_on_upload); -PUB void Mesh_Delete(Mesh* mesh); -Mesh* Mesh_Get(MeshHandle handle); -void Geometry_Destroy(Geometry* geometry); -MeshHandle Mesh_Insert(Mesh* mesh); -void Mesh_DebugPrint(Mesh* mesh); -MaterialHandle Material_Insert(Material* material); - -/** @brief gets render entities from a model and pushes them into a dynamic array for rendering */ -size_t ModelExtractRenderEnts(RenderEnt_darray* entities, ModelHandle model_handle, Mat4 affine, - RenderEntityFlags flags); - -// --- Drawing - -// NOTE: These functions use the globally bound camera in RenderScene -PUB void DrawMesh(Mesh* mesh, Material* material, Mat4 model); - -/** @brief the renderer does some internal bookkeeping for terrain so we use the terrain - stored on the Renderer rather than accept it as a parameter */ -PUB void Render_DrawTerrain(); - -// --- Getters (not in love with this but I'm finding keeping Renderer internals private to be okay) -arena* GetRenderFrameArena(Renderer* r); - -typedef struct RenderScene RenderScene; -typedef struct Shadow_Storage Shadow_Storage; -typedef struct Terrain_Storage Terrain_Storage; - -RenderScene* Render_GetScene(); -Shadow_Storage* Render_GetShadowStorage(); -Terrain_Storage* Render_GetTerrainStorage(); -Grid_Storage* Render_GetGridStorage(); -Immdraw_Storage* Render_GetImmdrawStorage(); -TextureHandle Render_GetWhiteTexture(); -arena* Render_GetFrameArena(); -Mesh_pool* Render_GetMeshPool(); -Material_pool* Render_GetMaterialPool(); - -// --- Setters -void Render_SetRenderMode(RenderMode mode); - -// ------------------------------------------------- - -// Frame lifecycle on CPU - -// 1. extract -// 2. culling -// 3. render -// 4. dispatch (combined with render for now) - -// typedef struct Cull_Result { -// u64 n_visible_objects; -// u64 n_culled_objects; -// u32* visible_ent_indices; // allocated on frame arena -// size_t index_count; -// } Cull_Result; - -// // everything that can be in the world, knows how to extract rendering data -// typedef void (*ExtractRenderData)(void* world_data); - -// typedef struct Renderer Renderer; - -// /** @brief Produces a smaller set of only those meshes visible in the camera frustum on the CPU -// */ Cull_Result Frame_Cull(Renderer* ren, RenderEnt* entities, size_t entity_count, Camera* -// camera); - -// Cull_Result Frame_Cull(Renderer* ren, RenderEnt* entities, size_t entity_count, Camera* camera) { -// // TODO: u32 chunk_count = Tpool_GetNumWorkers(); - -// arena* frame_arena = GetRenderFrameArena(ren); - -// Cull_Result result = { 0 }; -// result.visible_ent_indices = arena_alloc( -// frame_arena, sizeof(u32) * entity_count); // make space for if all ents are visible - -// assert((result.n_visible_objects + result.n_culled_objects == entity_count)); -// return result; -// } diff --git a/src/render/render_types.h b/src/render/render_types.h deleted file mode 100644 index bdf9849..0000000 --- a/src/render/render_types.h +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @brief - */ - -#pragma once -#include "animation.h" -#include "defines.h" -#include "maths_types.h" -#include "mem.h" -#include "ral_types.h" - -// --- Handles - -#define INVALID_MODEL_HANDLE ((ModelHandle){ .raw = 9999991 }) -#define INVALID_MATERIAL_HANDLE ((MaterialHandle){ .raw = 9999992 }) -#define INVALID_MESH_HANDLE ((MeshHandle){ .raw = 9999993 }) - -typedef enum RenderMode { - RENDER_MODE_DEFAULT, - RENDER_MODE_WIREFRAME, - RENDER_MODE_WIREFRAME_ON_LIT, - RENDER_MODE_COUNT -} RenderMode; - -typedef struct u32_opt { - u32 value; - bool has_value; -} u32_opt; - -typedef struct Mesh { - BufferHandle vertex_buffer; - BufferHandle index_buffer; - Geometry geometry; // NULL means it has been freed CPU-side - MaterialHandle material; - bool is_skinned; // false = its static - Armature armature; - bool is_uploaded; // has the data been uploaded to the GPU -} Mesh; -#ifndef TYPED_MESH_CONTAINERS -KITC_DECL_TYPED_ARRAY(Mesh) -TYPED_POOL(Mesh, Mesh) -#define TYPED_MESH_CONTAINERS -#endif - -typedef struct TextureData { - TextureDesc description; - void* image_data; -} TextureData; - -// --- Supported materials -typedef enum MaterialKind { - MAT_BLINN_PHONG, // NOTE: we're dropping support for this - MAT_PBR, // uses textures for PBR properties - MAT_PBR_PARAMS, // uses float values to represent a surface uniformly - MAT_COUNT -} MaterialKind; -static const char* material_kind_names[] = { "Blinn Phong", "PBR (Textures)", "PBR (Params)", - "Count (This should be an error)" }; - -/** - * @brief - * @note based on https://google.github.io/filament/Filament.html#materialsystem/standardmodel - */ -typedef struct Material { - char name[64]; - MaterialKind kind; // at the moment all materials are PBR materials - Vec3 base_colour; // linear RGB {0,0,0} to {1,1,1} - f32 metallic; - f32 roughness; - f32 ambient_occlusion; - TextureHandle albedo_map; - TextureHandle normal_map; - TextureHandle metallic_roughness_map; - TextureHandle ambient_occlusion_map; -} Material; - -#ifndef TYPED_MATERIAL_CONTAINERS -KITC_DECL_TYPED_ARRAY(Material) -TYPED_POOL(Material, Material) -#define TYPED_MATERIAL_CONTAINERS -#endif - -/** @brief Convenient wrapper around a number of meshes each with a material */ -typedef struct Model { - Str8 name; - MeshHandle* meshes; - size_t mesh_count; - MaterialHandle* materials; - size_t material_count; - arena anim_arena; - AnimationClip_darray* animations; -} Model; -#ifndef TYPED_MODEL_ARRAY -KITC_DECL_TYPED_ARRAY(Model) -#define TYPED_MODEL_ARRAY -#endif - -// TODO: function to create a model from a single mesh (like when using primitives) - -// --- Lights -typedef struct PointLight { - Vec3 position; - f32 constant, linear, quadratic; - Vec3 ambient; - Vec3 diffuse; - Vec3 specular; -} PointLight; - -typedef struct DirectionalLight { - Vec3 direction; - Vec3 ambient; - Vec3 diffuse; - Vec3 specular; -} DirectionalLight; - -// --- - -typedef enum RenderEntityFlag { - REND_ENT_CASTS_SHADOWS = 1 << 0, - REND_ENT_VISIBLE = 1 << 1, -} RenderEntityFlag; -typedef u32 RenderEntityFlags; - -/** @brief A renderable 'thing' */ -typedef struct RenderEnt { - MeshHandle mesh; - MaterialHandle material; - /** If NULL, no armature and the mesh is static geometry, else it is to be skinned */ - Armature* armature; - Mat4 affine; // In the future this should be updated by the transform graph - Bbox_3D bounding_box; - RenderEntityFlags flags; -} RenderEnt; - -#ifndef TYPED_RENDERENT_ARRAY -KITC_DECL_TYPED_ARRAY(RenderEnt) -#define TYPED_RENDERENT_ARRAY -#endif diff --git a/src/render/shader_layouts.h b/src/render/shader_layouts.h deleted file mode 100644 index ef94c89..0000000 --- a/src/render/shader_layouts.h +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once -#include "maths_types.h" -#include "ral_types.h" - -/** @brief shader layout for camera matrices */ -typedef struct Binding_Camera { - Mat4 view; - Mat4 projection; - Vec4 viewPos; -} Binding_Camera; - -typedef struct Binding_Model { - Mat4 model; -} Binding_Model; - -/** @brief data that is handy to have in any shader */ -typedef struct Binding_Globals { -} Binding_Globals; - -typedef struct pbr_point_light { - Vec3 pos; - f32 pad; - Vec3 color; - f32 pad2; -} pbr_point_light; - -typedef struct Binding_Lights { - pbr_point_light pointLights[4]; -} Binding_Lights; - -static ShaderDataLayout Binding_Camera_GetLayout(void* data) { - Binding_Camera* d = data; - bool has_data = data != NULL; - - ShaderBinding b1 = { .label = "Camera", - .kind = BINDING_BYTES, - .data.bytes = { .size = sizeof(Binding_Camera) } }; - if (has_data) { - b1.data.bytes.data = d; - } - return (ShaderDataLayout){ .bindings = { b1 }, .binding_count = 1 }; -} - -static ShaderDataLayout Binding_Model_GetLayout(void* data) { - Binding_Model* d = data; - bool has_data = data != NULL; - - ShaderBinding b1 = { .label = "Model", - .kind = BINDING_BYTES, - .vis = VISIBILITY_VERTEX, - .data.bytes = { .size = sizeof(Binding_Model) } }; - if (has_data) { - b1.data.bytes.data = d; - } - return (ShaderDataLayout){ .bindings = { b1 }, .binding_count = 1 }; -} - -static ShaderDataLayout Binding_Lights_GetLayout(void* data) { - Binding_Lights* d = data; - bool has_data = data != NULL; - - ShaderBinding b1 = { .label = "Lights", - .kind = BINDING_BYTES, - .vis = VISIBILITY_FRAGMENT, - .data.bytes = { .size = sizeof(Binding_Lights) } }; - if (has_data) { - b1.data.bytes.data = d; - } - return (ShaderDataLayout){ .bindings = { b1 }, .binding_count = 1 }; -} diff --git a/src/render/shadows.c b/src/render/shadows.c deleted file mode 100644 index 029eefb..0000000 --- a/src/render/shadows.c +++ /dev/null @@ -1,211 +0,0 @@ -#include "shadows.h" -#include <string.h> -#include "file.h" -#include "glad/glad.h" -#include "log.h" -#include "maths.h" -#include "maths_types.h" -#include "primitives.h" -#include "ral_common.h" -#include "ral_impl.h" -#include "ral_types.h" -#include "render.h" -#include "render_types.h" -#include "str.h" - -ShaderDataLayout ShadowUniforms_GetLayout(void* data) { - ShadowUniforms* d = (ShadowUniforms*)data; - bool has_data = data != NULL; - - ShaderBinding b1 = { - .label = "ShadowUniforms", - .kind = BINDING_BYTES, - .vis = VISIBILITY_VERTEX, - .data = { .bytes = { .size = sizeof(ShadowUniforms) } } - // TODO: split this into two bindings so we can update model matrix independently - }; - - if (has_data) { - b1.data.bytes.data = data; - } - - return (ShaderDataLayout){ .binding_count = 1, .bindings = { b1 } }; -} - -ShaderDataLayout ShadowDebugQuad_GetLayout(void* data) { - TextureHandle* handle = data; - bool has_data = data != NULL; - - ShaderBinding b1 = { - .label = "depthMap", - .kind = BINDING_TEXTURE, - .vis = VISIBILITY_FRAGMENT, - }; - - if (has_data) { - b1.data.texture.handle = *handle; - } - - return (ShaderDataLayout){ .binding_count = 1, .bindings = { b1 } }; -} - -void Shadow_Init(Shadow_Storage* storage, u32 shadowmap_width, u32 shadowmap_height) { - memset(storage, 0, sizeof(Shadow_Storage)); - arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); - - TextureDesc depthmap_desc = { .extents = u32x2(shadowmap_width, shadowmap_height), - .format = TEXTURE_FORMAT_DEPTH_DEFAULT, - .tex_type = TEXTURE_TYPE_2D }; - DEBUG("Creating depth map texture for shadows"); - TextureHandle depthmap = GPU_TextureCreate(depthmap_desc, false, NULL); - storage->depth_texture = depthmap; - - // -- shadowmap drawing pass - GPU_RenderpassDesc rpass_desc = { .default_framebuffer = false, - .has_color_target = false, - .has_depth_stencil = true, - .depth_stencil = depthmap }; - - storage->shadowmap_pass = GPU_Renderpass_Create(rpass_desc); - - WARN("About to laod shaders"); - WARN("Shader paths: %s %s", "assets/shaders/shadows.vert", "assets/shaders/shadows.frag"); - Str8 vert_path = str8("assets/shaders/shadows.vert"); - Str8 frag_path = str8("assets/shaders/shadows.frag"); - str8_opt vertex_shader = str8_from_file(&scratch, vert_path); - str8_opt fragment_shader = str8_from_file(&scratch, frag_path); - if (!vertex_shader.has_value || !fragment_shader.has_value) { - ERROR_EXIT("Failed to load shaders from disk"); - } - - ShaderDataLayout uniforms = ShadowUniforms_GetLayout(NULL); - - GraphicsPipelineDesc pipeline_desc = { - .debug_name = "Shadows Pipeline", - .vertex_desc = static_3d_vertex_description(), - .data_layouts = { uniforms }, - .data_layouts_count = 1, - .vs = { .debug_name = "Shadows Vert shader", - .filepath = vert_path, - .code = vertex_shader.contents, - .is_spirv = false }, - .fs = { .debug_name = "Shadows Frag shader", - .filepath = frag_path, - .code = fragment_shader.contents, - .is_spirv = false }, - }; - storage->shadowmap_pipeline = GPU_GraphicsPipeline_Create(pipeline_desc, storage->shadowmap_pass); - - // -- debug quad pipeline - GPU_RenderpassDesc debug_pass_desc = { .default_framebuffer = true }; - storage->debugquad_pass = GPU_Renderpass_Create(debug_pass_desc); - - vert_path = str8("assets/shaders/debug_quad.vert"); - frag_path = str8("assets/shaders/debug_quad.frag"); - vertex_shader = str8_from_file(&scratch, vert_path); - fragment_shader = str8_from_file(&scratch, frag_path); - if (!vertex_shader.has_value || !fragment_shader.has_value) { - ERROR_EXIT("Failed to load shaders from disk"); - } - - ShaderDataLayout debugquad_uniforms = ShadowDebugQuad_GetLayout(NULL); - - GraphicsPipelineDesc debugquad_pipeline_desc = { - .debug_name = "Shadows debug quad Pipeline", - .vertex_desc = static_3d_vertex_description(), - .data_layouts = { debugquad_uniforms }, - .data_layouts_count = 1, - .vs = { .debug_name = "depth debug quad vert shader", - .filepath = vert_path, - .code = vertex_shader.contents, - .is_spirv = false }, - .fs = { .debug_name = "depth debug quad frag shader", - .filepath = frag_path, - .code = fragment_shader.contents, - .is_spirv = false }, - }; - storage->debugquad_pipeline = - GPU_GraphicsPipeline_Create(debugquad_pipeline_desc, storage->debugquad_pass); - - Geometry quad_geo = Geo_CreatePlane(f32x2(1, 1), 1, 1); - // HACK: Swap vertices to make it face us - Vertex top0 = quad_geo.vertices->data[0]; - quad_geo.vertices->data[0] = quad_geo.vertices->data[2]; - quad_geo.vertices->data[2] = top0; - Vertex top1 = quad_geo.vertices->data[1]; - quad_geo.vertices->data[1] = quad_geo.vertices->data[3]; - quad_geo.vertices->data[3] = top1; - storage->quad = Mesh_Create(&quad_geo, false); - - arena_free_storage(&scratch); -} - -void Shadow_Run(RenderEnt* entities, size_t entity_count) { - Shadow_Storage* shadow_storage = Render_GetShadowStorage(); - - // calculations - RenderScene* render_scene = Render_GetScene(); - f32 near_plane = 1.0, far_plane = 10.0; - // -- Not sure about how we want to handle lights - Vec3 light_position = { 1, 4, -1 }; - // -- - Mat4 light_projection = mat4_orthographic(-10.0, 10.0, -10.0, 10.0, near_plane, far_plane); - Mat4 light_view = mat4_look_at(light_position, VEC3_ZERO, VEC3_Y); - Mat4 light_space_matrix = mat4_mult(light_view, light_projection); - - Shadow_ShadowmapExecute(shadow_storage, light_space_matrix, entities, entity_count); -} - -void Shadow_DrawDebugQuad() { - Shadow_Storage* shadow_storage = Render_GetShadowStorage(); - - GPU_CmdEncoder* enc = GPU_GetDefaultEncoder(); - GPU_CmdEncoder_BeginRender(enc, shadow_storage->debugquad_pass); - - GPU_EncodeBindPipeline(enc, shadow_storage->debugquad_pipeline); - ShaderDataLayout quad_data = ShadowDebugQuad_GetLayout(&shadow_storage->depth_texture); - GPU_EncodeBindShaderData(enc, 0, quad_data); - GPU_EncodeSetVertexBuffer(enc, shadow_storage->quad.vertex_buffer); - GPU_EncodeSetIndexBuffer(enc, shadow_storage->quad.index_buffer); - GPU_EncodeDrawIndexedTris(enc, shadow_storage->quad.geometry.indices->len); - - GPU_CmdEncoder_EndRender(enc); -} - -void Shadow_ShadowmapExecute(Shadow_Storage* storage, Mat4 light_space_transform, - RenderEnt* entities, size_t entity_count) { - GPU_CmdEncoder shadow_encoder = GPU_CmdEncoder_Create(); - - GPU_CmdEncoder_BeginRender(&shadow_encoder, storage->shadowmap_pass); - // DEBUG("Begin shadowmap renderpass"); - - // FIXME: shouldnt be gl specific - glClear(GL_DEPTH_BUFFER_BIT); - - GPU_EncodeBindPipeline(&shadow_encoder, storage->shadowmap_pipeline); - - ShadowUniforms uniforms = { - .light_space = light_space_transform, - .model = mat4_ident() // this will be overwritten for each Model - }; - ShaderDataLayout shader_data = ShadowUniforms_GetLayout(&uniforms); - - for (size_t ent_i = 0; ent_i < entity_count; ent_i++) { - RenderEnt renderable = entities[ent_i]; - if (renderable.flags && REND_ENT_CASTS_SHADOWS) { - // Model* model = MODEL_GET(renderable.model); - - uniforms.model = renderable.affine; // update the model transform - - Mesh* mesh = Mesh_pool_get(Render_GetMeshPool(), renderable.mesh); - GPU_EncodeBindShaderData(&shadow_encoder, 0, shader_data); - GPU_EncodeSetVertexBuffer(&shadow_encoder, mesh->vertex_buffer); - GPU_EncodeSetIndexBuffer(&shadow_encoder, mesh->index_buffer); - GPU_EncodeDrawIndexedTris(&shadow_encoder, mesh->geometry.indices->len); - } - } - - GPU_CmdEncoder_EndRender(&shadow_encoder); // end renderpass -} - -TextureHandle Shadow_GetShadowMapTexture(Shadow_Storage* storage) { return storage->depth_texture; } diff --git a/src/render/shadows.h b/src/render/shadows.h deleted file mode 100644 index 0482d10..0000000 --- a/src/render/shadows.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @brief Functions for adding shadows to scene rendering. - */ - -#pragma once -#include "defines.h" -#include "ral_impl.h" -#include "ral_types.h" -#include "render_types.h" - -typedef struct Shadow_Storage { - bool enabled; - GPU_Renderpass* shadowmap_pass; - GPU_Pipeline* shadowmap_pipeline; - TextureHandle depth_texture; - bool debug_quad_enabled; - Mesh quad; - GPU_Renderpass* debugquad_pass; - GPU_Pipeline* debugquad_pipeline; - // TODO: Some statistics tracking -} Shadow_Storage; - -typedef struct ShadowUniforms { - Mat4 light_space; - Mat4 model; -} ShadowUniforms; - -typedef struct Camera Camera; -typedef struct Mat4 Mat4; - -// --- Public API -PUB void Shadow_Init(Shadow_Storage* storage, u32 shadowmap_width, u32 shadowmap_height); - -/** @brief Run shadow map generation for given entities, and store in a texture. - * @note Uses active directional light for now */ -PUB void Shadow_Run(RenderEnt* entities, size_t entity_count); - -PUB void Shadow_DrawDebugQuad(); - -/** @brief Get the shadow texture generated from shadowmap pass */ -PUB TextureHandle Shadow_GetShadowMapTexture(Shadow_Storage* storage); - -// --- Internal -GPU_Renderpass* Shadow_RPassCreate(); // Creates the render pass -GPU_Pipeline* Shadow_PipelineCreate(GPU_Renderpass* rpass); // Creates the pipeline -void Shadow_ShadowmapExecute(Shadow_Storage* storage, Mat4 light_space_transform, - RenderEnt* entities, size_t entity_count); -void Shadow_RenderDebugQuad(); diff --git a/src/render/skybox.c b/src/render/skybox.c deleted file mode 100644 index b4e1e42..0000000 --- a/src/render/skybox.c +++ /dev/null @@ -1,161 +0,0 @@ -#include "skybox.h" -#include <assert.h> -#include "file.h" -#include "glad/glad.h" -#include "log.h" -#include "maths.h" -#include "primitives.h" -#include "ral_common.h" -#include "ral_impl.h" -#include "ral_types.h" -#include "render.h" -#include "render_types.h" -#include "shader_layouts.h" - -float skyboxVertices[] = { - // positions - -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, - - -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, - -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, - - 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, - - -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, - - -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, - - -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f -}; - -static const char* faces[6] = { "assets/demo/skybox/right.jpg", "assets/demo/skybox/left.jpg", - "assets/demo/skybox/top.jpg", "assets/demo/skybox/bottom.jpg", - "assets/demo/skybox/front.jpg", "assets/demo/skybox/back.jpg" }; - -Skybox Skybox_Create(const char** face_paths, int n) { - INFO("Creating a skybox"); - CASSERT_MSG( - n == 6, - "We only support full cubemaps for now"); // ! we're only supporting a full cubemap for now - - // -- cube verts - Geometry geom = { .format = VERTEX_POS_ONLY, // doesnt matter - .has_indices = false, - .indices = NULL, - .vertices = Vertex_darray_new(36) }; - for (u32 i = 0; i < (36 * 3); i += 3) { - Vertex_darray_push( - geom.vertices, - (Vertex){ .pos_only = { .position = vec3(skyboxVertices[i], skyboxVertices[i + 1], - skyboxVertices[i + 2]) } }); - } - Mesh cube = Mesh_Create(&geom, false); - - // -- cubemap texture - TextureHandle handle; - GPU_Texture* tex = GPU_TextureAlloc(&handle); - glBindTexture(GL_TEXTURE_CUBE_MAP, tex->id); - - for (unsigned int i = 0; i < n; i++) { - TextureData data = TextureDataLoad(face_paths[i], false); - assert(data.description.format == TEXTURE_FORMAT_8_8_8_RGB_UNORM); - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, data.description.extents.x, - data.description.extents.y, 0, GL_RGB, GL_UNSIGNED_BYTE, data.image_data); - } - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - - // shader pipeline - GPU_RenderpassDesc rpass_desc = { - .default_framebuffer = true, - }; - GPU_Renderpass* pass = GPU_Renderpass_Create(rpass_desc); - - arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); - - Str8 vert_path = str8("assets/shaders/skybox.vert"); - Str8 frag_path = str8("assets/shaders/skybox.frag"); - str8_opt vertex_shader = str8_from_file(&scratch, vert_path); - str8_opt fragment_shader = str8_from_file(&scratch, frag_path); - if (!vertex_shader.has_value || !fragment_shader.has_value) { - ERROR_EXIT("Failed to load shaders from disk") - } - - ShaderDataLayout camera_data = Binding_Camera_GetLayout(NULL); - ShaderDataLayout shader_data = Skybox_GetLayout(NULL); - - VertexDescription builder = { .debug_label = "pos only" }; - VertexDesc_AddAttr(&builder, "inPosition", ATTR_F32x3); - builder.use_full_vertex_size = true; - - GraphicsPipelineDesc pipeline_desc = { - .debug_name = "Skybox pipeline", - .vertex_desc = builder, - .data_layouts = { shader_data, camera_data }, - .data_layouts_count = 2, - .vs = { .debug_name = "Skybox Vertex Shader", - .filepath = vert_path, - .code = vertex_shader.contents }, - .fs = { .debug_name = "Skybox Fragment Shader", - .filepath = frag_path, - .code = fragment_shader.contents }, - .wireframe = false, - .depth_test = true, - }; - - GPU_Pipeline* pipeline = GPU_GraphicsPipeline_Create(pipeline_desc, pass); - - return (Skybox){ .cube = cube, .texture = handle, .pipeline = pipeline }; -} - -Skybox Skybox_Default() { return Skybox_Create(faces, 6); } - -void Skybox_Draw(Skybox* skybox, Camera camera) { - GPU_CmdEncoder* enc = GPU_GetDefaultEncoder(); - glDepthFunc(GL_LEQUAL); - GPU_CmdEncoder_BeginRender(enc, skybox->pipeline->renderpass); - GPU_EncodeBindPipeline(enc, skybox->pipeline); - GPU_EncodeSetDefaults(enc); - - // Shader data - - Mat4 view, proj; - u32x2 dimensions = GPU_Swapchain_GetDimensions(); - Camera_ViewProj(&camera, dimensions.x, dimensions.y, &view, &proj); - Mat4 new = mat4_ident(); - new.data[0] = view.data[0]; - new.data[1] = view.data[1]; - new.data[2] = view.data[2]; - new.data[4] = view.data[4]; - new.data[5] = view.data[5]; - new.data[6] = view.data[6]; - new.data[8] = view.data[8]; - new.data[9] = view.data[9]; - new.data[10] = view.data[10]; - - Binding_Camera camera_data = { .view = new, - .projection = proj, - .viewPos = vec4(camera.position.x, camera.position.y, - camera.position.z, 1.0) }; - GPU_EncodeBindShaderData(enc, 0, Binding_Camera_GetLayout(&camera_data)); - - SkyboxUniforms uniforms = { .cubemap = skybox->texture }; - ShaderDataLayout skybox_data = Skybox_GetLayout(&uniforms); - GPU_EncodeBindShaderData(enc, 0, skybox_data); - - GPU_EncodeSetVertexBuffer(enc, skybox->cube.vertex_buffer); - GPU_EncodeSetIndexBuffer(enc, skybox->cube.index_buffer); - - GPU_EncodeDrawTris(enc, 36); - - GPU_CmdEncoder_EndRender(enc); - glDepthFunc(GL_LESS); -} diff --git a/src/render/skybox.h b/src/render/skybox.h deleted file mode 100644 index c2ef3a2..0000000 --- a/src/render/skybox.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @brief - */ - -#pragma once -#include "camera.h" -#include "defines.h" -#include "ral_impl.h" -#include "render_types.h" - -typedef struct Skybox { - Mesh cube; - TextureHandle texture; - GPU_Pipeline* pipeline; // "shader" -} Skybox; - -PUB Skybox Skybox_Create(const char** face_paths, int n); // should always pass n = 6 for now - -PUB void Skybox_Draw(Skybox* skybox, Camera camera); - -typedef struct SkyboxUniforms { - TextureHandle cubemap; -} SkyboxUniforms; - -static ShaderDataLayout Skybox_GetLayout(void* data) { - SkyboxUniforms* d = (SkyboxUniforms*)data; // cold cast - bool has_data = data != NULL; - - ShaderBinding b1 = { - .label = "cubeMap", - .vis = VISIBILITY_FRAGMENT, - .kind = BINDING_TEXTURE, - }; - - if (has_data) { - b1.data.texture.handle = d->cubemap; - } - return (ShaderDataLayout){ .bindings = { b1 }, .binding_count = 1 }; -} - -Skybox Skybox_Default();
\ No newline at end of file diff --git a/src/resources/gltf.c b/src/resources/gltf.c deleted file mode 100644 index 66ae1b6..0000000 --- a/src/resources/gltf.c +++ /dev/null @@ -1,596 +0,0 @@ -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include "animation.h" -#include "colours.h" -#include "core.h" -#include "defines.h" -#include "file.h" -#include "loaders.h" -#include "log.h" -#include "maths.h" -#include "maths_types.h" -#include "mem.h" -#include "pbr.h" -#include "platform.h" -#include "ral_types.h" -#include "render.h" -#include "render_types.h" -#include "str.h" - -#define CGLTF_IMPLEMENTATION -#include <cgltf.h> - -extern Core g_core; - -/* GLTF Loading Pipeline - ===================== */ - -struct face { - cgltf_uint indices[3]; -}; -typedef struct face face; - -KITC_DECL_TYPED_ARRAY(Vec3) -KITC_DECL_TYPED_ARRAY(Vec2) -KITC_DECL_TYPED_ARRAY(Vec4u) -KITC_DECL_TYPED_ARRAY(Vec4i) -KITC_DECL_TYPED_ARRAY(Vec4) -KITC_DECL_TYPED_ARRAY(face) -KITC_DECL_TYPED_ARRAY(i32) - -size_t GLTF_LoadMaterials(cgltf_data* data, Str8 relative_path, Material_darray* out_materials); - -ModelHandle ModelLoad_gltf(const char* path, bool invert_texture_y) { - size_t arena_size = MB(1); - arena scratch = arena_create(malloc(arena_size), arena_size); - - TRACE("Loading model at Path %s\n", path); - path_opt relative_path = path_parent(&scratch, path); - if (!relative_path.has_value) { - WARN("Couldnt get a relative path for the path to use for loading materials & textures later"); - } - const char* file_string = string_from_file(path); - - ModelHandle handle; - Model* model = Model_pool_alloc(&g_core.models, &handle); - model->name = Str8_cstr_view(path); - - bool success = - model_load_gltf_str(file_string, path, relative_path.path, model, invert_texture_y); - - if (!success) { - FATAL("Couldnt load GLTF file at path %s", path); - ERROR_EXIT("Load fails are considered crash-worthy right now. This will change later.\n"); - } - - arena_free_all(&scratch); - arena_free_storage(&scratch); - return handle; -} - -void assert_path_type_matches_component_type(cgltf_animation_path_type target_path, - cgltf_accessor* output) { - if (target_path == cgltf_animation_path_type_rotation) { - assert(output->component_type == cgltf_component_type_r_32f); - assert(output->type == cgltf_type_vec4); - } -} - -// TODO: Brainstorm how I can make this simpler and break it up into more testable pieces - -void load_position_components(Vec3_darray* positions, cgltf_accessor* accessor) { - TRACE("Loading %d vec3 position components", accessor->count); - CASSERT_MSG(accessor->component_type == cgltf_component_type_r_32f, - "Positions components are floats"); - CASSERT_MSG(accessor->type == cgltf_type_vec3, "Vertex positions should be a vec3"); - - for (cgltf_size v = 0; v < accessor->count; ++v) { - Vec3 pos; - cgltf_accessor_read_float(accessor, v, &pos.x, 3); - Vec3_darray_push(positions, pos); - } -} - -void load_normal_components(Vec3_darray* normals, cgltf_accessor* accessor) { - TRACE("Loading %d vec3 normal components", accessor->count); - CASSERT_MSG(accessor->component_type == cgltf_component_type_r_32f, - "Normal vector components are floats"); - CASSERT_MSG(accessor->type == cgltf_type_vec3, "Vertex normals should be a vec3"); - - for (cgltf_size v = 0; v < accessor->count; ++v) { - Vec3 pos; - cgltf_accessor_read_float(accessor, v, &pos.x, 3); - Vec3_darray_push(normals, pos); - } -} - -void load_texcoord_components(Vec2_darray* texcoords, cgltf_accessor* accessor) { - TRACE("Load texture coordinates from accessor"); - CASSERT(accessor->component_type == cgltf_component_type_r_32f); - CASSERT_MSG(accessor->type == cgltf_type_vec2, "Texture coordinates should be a vec2"); - - for (cgltf_size v = 0; v < accessor->count; ++v) { - Vec2 tex; - bool success = cgltf_accessor_read_float(accessor, v, &tex.x, 2); - if (!success) { - ERROR("Error loading tex coord"); - } - Vec2_darray_push(texcoords, tex); - } -} - -void load_joint_index_components(Vec4i_darray* joint_indices, cgltf_accessor* accessor) { - TRACE("Load joint indices from accessor"); - CASSERT(accessor->component_type == cgltf_component_type_r_16u); - CASSERT_MSG(accessor->type == cgltf_type_vec4, "Joint indices should be a vec4"); - Vec4i tmp_joint_index; - Vec4 joints_as_floats; - for (cgltf_size v = 0; v < accessor->count; ++v) { - cgltf_accessor_read_float(accessor, v, &joints_as_floats.x, 4); - tmp_joint_index.x = (u32)joints_as_floats.x; - tmp_joint_index.y = (u32)joints_as_floats.y; - tmp_joint_index.z = (u32)joints_as_floats.z; - tmp_joint_index.w = (u32)joints_as_floats.w; - printf("Joints affecting vertex %d : %d %d %d %d\n", v, tmp_joint_index.x, tmp_joint_index.y, - tmp_joint_index.z, tmp_joint_index.w); - Vec4i_darray_push(joint_indices, tmp_joint_index); - } -} - -bool model_load_gltf_str(const char* file_string, const char* filepath, Str8 relative_path, - Model* out_model, bool invert_textures_y) { - TRACE("Load GLTF from string"); - - // Setup temps - Vec3_darray* tmp_positions = Vec3_darray_new(1000); - Vec3_darray* tmp_normals = Vec3_darray_new(1000); - Vec2_darray* tmp_uvs = Vec2_darray_new(1000); - Vec4i_darray* tmp_joint_indices = Vec4i_darray_new(1000); - Vec4_darray* tmp_weights = Vec4_darray_new(1000); - Material_darray* tmp_materials = Material_darray_new(1); - Mesh_darray* tmp_meshes = Mesh_darray_new(1); - i32_darray* tmp_material_indexes = i32_darray_new(1); - - Joint_darray* joints = Joint_darray_new(256); - - cgltf_options options = { 0 }; - cgltf_data* data = NULL; - cgltf_result result = cgltf_parse_file(&options, filepath, &data); - if (result != cgltf_result_success) { - WARN("gltf load failed"); - // TODO: cleanup arrays(allocate all from arena ?) - return false; - } - - cgltf_load_buffers(&options, data, filepath); - DEBUG("loaded buffers"); - - // --- Skin - size_t num_skins = data->skins_count; - bool is_skinned = false; - Armature main_skeleton = { 0 }; - if (num_skins == 1) { - is_skinned = true; - } else if (num_skins > 1) { - WARN("GLTF files with more than 1 skin are not supported"); - return false; - } - - if (is_skinned) { - cgltf_skin* gltf_skin = data->skins; - DEBUG("loading skin %s", gltf_skin->name); - size_t num_joints = gltf_skin->joints_count; - DEBUG("# Joints %d", num_joints); - - // Create our data that will be placed onto the model - Armature armature = { .label = "test_skin" }; - printf("Skin %s\n", gltf_skin->name); - // armature.label = Clone_cstr(&armature.arena, gltf_skin->name); - armature.joints = joints; // ! Make sure not to free this - - cgltf_accessor* gltf_inverse_bind_matrices = gltf_skin->inverse_bind_matrices; - - // --- Joints - // for each one we'll spit out a joint - for (size_t i = 0; i < num_joints; i++) { - // Get the joint and assign its node index for later referencing - cgltf_node* joint_node = gltf_skin->joints[i]; - TRACE("Joint %d (node index %d)", i, cgltf_node_index(data, joint_node)); - Joint joint_i = { .debug_label = "test_joint", - .node_idx = cgltf_node_index(data, joint_node), - .inverse_bind_matrix = mat4_ident() }; - - if (joint_node->children_count > 0 && !joint_node->has_translation && - !joint_node->has_rotation) { - WARN("Joint node with index %d is the root node", i); - joint_i.transform_components = TRANSFORM_DEFAULT; - joint_i.parent = -1; - for (u32 c_i = 0; c_i < joint_node->children_count; c_i++) { - joint_i.children[c_i] = cgltf_node_index(data, joint_node->children[c_i]); - joint_i.children_count++; - } - } else { - TRACE("Storing joint transform"); - joint_i.transform_components = TRANSFORM_DEFAULT; - if (joint_node->has_translation) { - memcpy(&joint_i.transform_components.position, &joint_node->translation, 3 * sizeof(f32)); - } - if (joint_node->has_rotation) { - memcpy(&joint_i.transform_components.rotation, &joint_node->rotation, 4 * sizeof(f32)); - } - if (joint_node->has_scale) { - memcpy(&joint_i.transform_components.scale, &joint_node->scale, 3 * sizeof(f32)); - } - joint_i.parent = cgltf_node_index(data, joint_node->parent); - } - // Calculate and store the starting transform of the joint - joint_i.local_transform = transform_to_mat(&joint_i.transform_components); - // Read in the inverse bind matrix - cgltf_accessor_read_float(gltf_inverse_bind_matrices, i, &joint_i.inverse_bind_matrix.data[0], - 16); - Joint_darray_push(armature.joints, joint_i); - } - main_skeleton = armature; - // out_model->armature = armature; - // out_model->has_joints = true; - } - - // --- Materials - size_t num_materials = GLTF_LoadMaterials(data, relative_path, tmp_materials); - - // --- Meshes - size_t num_meshes = data->meshes_count; - TRACE("Num meshes %d", num_meshes); - for (size_t m = 0; m < num_meshes; m++) { - printf("Primitive count %d\n", data->meshes[m].primitives_count); - for (size_t prim_i = 0; prim_i < data->meshes[m].primitives_count; prim_i++) { - DEBUG("Primitive %d\n", prim_i); - - cgltf_primitive primitive = data->meshes[m].primitives[prim_i]; - DEBUG("Found %d attributes", primitive.attributes_count); - - for (cgltf_size a = 0; a < primitive.attributes_count; a++) { - cgltf_attribute attribute = primitive.attributes[a]; - if (attribute.type == cgltf_attribute_type_position) { - cgltf_accessor* accessor = attribute.data; - load_position_components(tmp_positions, accessor); - } else if (attribute.type == cgltf_attribute_type_normal) { - cgltf_accessor* accessor = attribute.data; - load_normal_components(tmp_normals, accessor); - } else if (attribute.type == cgltf_attribute_type_texcoord) { - cgltf_accessor* accessor = attribute.data; - load_texcoord_components(tmp_uvs, accessor); - } else if (attribute.type == cgltf_attribute_type_joints) { - TRACE("Load joint indices from accessor"); - cgltf_accessor* accessor = attribute.data; - load_joint_index_components(tmp_joint_indices, accessor); - } else if (attribute.type == cgltf_attribute_type_weights) { - TRACE("Load joint weights from accessor"); - cgltf_accessor* accessor = attribute.data; - CASSERT(accessor->component_type == cgltf_component_type_r_32f); - CASSERT(accessor->type == cgltf_type_vec4); - - for (cgltf_size v = 0; v < accessor->count; ++v) { - Vec4 weights; - cgltf_accessor_read_float(accessor, v, &weights.x, 4); - printf("Weights affecting vertex %d : %f %f %f %f\n", v, weights.x, weights.y, - weights.z, weights.w); - Vec4_darray_push(tmp_weights, weights); - } - } else { - WARN("Unhandled cgltf_attribute_type: %s. skipping..", attribute.name); - } - } - // mesh.vertex_bone_data = vertex_bone_data_darray_new(1); - i32 mat_idx = -1; - if (primitive.material != NULL) { - DEBUG("Primitive Material %s", primitive.material->name); - // FIXME! - for (u32 i = 0; i < Material_darray_len(tmp_materials); i++) { - printf("%s vs %s \n", primitive.material->name, tmp_materials->data[i].name); - if (strcmp(primitive.material->name, tmp_materials->data[i].name) == 0) { - INFO("Found material"); - mat_idx = i; - i32_darray_push(tmp_material_indexes, mat_idx); - break; - } - } - } else { - i32_darray_push(tmp_material_indexes, -1); - } - - TRACE("Vertex data has been loaded"); - - Vertex_darray* geo_vertices = Vertex_darray_new(3); - u32_darray* geo_indices = u32_darray_new(0); - - // Store vertices - printf("Positions %d Normals %d UVs %d\n", tmp_positions->len, tmp_normals->len, - tmp_uvs->len); - // assert(tmp_positions->len == tmp_normals->len); - // assert(tmp_normals->len == tmp_uvs->len); - bool has_normals = tmp_normals->len > 0; - bool has_uvs = tmp_uvs->len > 0; - for (u32 v_i = 0; v_i < tmp_positions->len; v_i++) { - Vertex v = { 0 }; - if (is_skinned) { - v.skinned_3d.position = tmp_positions->data[v_i]; - v.skinned_3d.normal = has_normals ? tmp_normals->data[v_i] : VEC3_ZERO, - v.skinned_3d.tex_coords = has_uvs ? tmp_uvs->data[v_i] : vec2_create(0., 0.); - v.skinned_3d.bone_ids = tmp_joint_indices->data[v_i]; - v.skinned_3d.bone_weights = tmp_weights->data[v_i]; - } else { - v.static_3d.position = tmp_positions->data[v_i]; - v.static_3d.normal = has_normals ? tmp_normals->data[v_i] : VEC3_ZERO, - v.static_3d.tex_coords = has_uvs ? tmp_uvs->data[v_i] : vec2_create(0., 0.); - } - Vertex_darray_push(geo_vertices, v); - }; - - // Store indices - cgltf_accessor* indices = primitive.indices; - if (primitive.indices > 0) { - WARN("indices! %d", indices->count); - - // store indices - for (cgltf_size i = 0; i < indices->count; ++i) { - cgltf_uint ei; - cgltf_accessor_read_uint(indices, i, &ei, 1); - u32_darray_push(geo_indices, ei); - } - - Geometry* geometry = malloc(sizeof(Geometry)); - geometry->format = is_skinned ? VERTEX_SKINNED : VERTEX_STATIC_3D; - geometry->has_indices = true; - geometry->vertices = geo_vertices; - geometry->indices = geo_indices; - geometry->index_count = geo_indices->len; - - Mesh m = Mesh_Create(geometry, false); - if (is_skinned) { - m.is_skinned = true; - m.armature = main_skeleton; - } - Mesh_darray_push(tmp_meshes, m); - - Vec3_darray_clear(tmp_positions); - Vec3_darray_clear(tmp_normals); - Vec2_darray_clear(tmp_uvs); - Vec4i_darray_clear(tmp_joint_indices); - Vec4_darray_clear(tmp_weights); - } else { - WARN("No indices found. Ignoring mesh..."); - } - } - - // --- Animations - size_t num_animations = data->animations_count; - TRACE("Num animations %d", num_animations); - - if (num_animations > 0) { - if (!out_model->animations) { - out_model->animations = AnimationClip_darray_new(num_animations); - } - out_model->anim_arena = arena_create(malloc(MB(1)), MB(1)); - arena* arena = &out_model->anim_arena; - - // Iterate over each animation in the GLTF - for (int anim_idx = 0; anim_idx < data->animations_count; anim_idx++) { - cgltf_animation animation = data->animations[anim_idx]; - AnimationClip clip = { 0 }; - clip.clip_name = "test anim clip"; - clip.channels = AnimationSampler_darray_new(1); - - // for each animation, loop through all the channels - for (size_t c = 0; c < animation.channels_count; c++) { - cgltf_animation_channel channel = animation.channels[c]; - - AnimationSampler sampler = { 0 }; - - KeyframeKind data_type; - - switch (channel.target_path) { - case cgltf_animation_path_type_rotation: - data_type = KEYFRAME_ROTATION; - break; - case cgltf_animation_path_type_translation: - data_type = KEYFRAME_TRANSLATION; - break; - case cgltf_animation_path_type_scale: - data_type = KEYFRAME_SCALE; - break; - case cgltf_animation_path_type_weights: - data_type = KEYFRAME_WEIGHTS; - WARN("Morph target weights arent supported yet"); - return false; - default: - WARN("unsupported animation type"); - return false; - } - - sampler.current_index = 0; - sampler.animation.interpolation = INTERPOLATION_LINEAR; // NOTE: hardcoded for now - - // Keyframe times - size_t n_frames = channel.sampler->input->count; - CASSERT_MSG(channel.sampler->input->component_type == cgltf_component_type_r_32f, - "Expected animation sampler input component to be type f32"); - f32* times = arena_alloc(arena, n_frames * sizeof(f32)); - sampler.animation.n_timestamps = n_frames; - sampler.animation.timestamps = times; - cgltf_accessor_unpack_floats(channel.sampler->input, times, n_frames); - - // Keyframe values - size_t n_values = channel.sampler->output->count; - CASSERT_MSG(n_frames == n_values, "keyframe times = keyframe values"); - - Keyframes keyframes = { 0 }; - keyframes.kind = data_type; - keyframes.count = n_values; - keyframes.values = arena_alloc(arena, n_values * sizeof(Keyframe)); - for (cgltf_size v = 0; v < channel.sampler->output->count; ++v) { - switch (data_type) { - case KEYFRAME_ROTATION: { - Quat rot; - cgltf_accessor_read_float(channel.sampler->output, v, &rot.x, 4); - // printf("Quat %f %f %f %f\n", rot.x, rot.y, rot.z, rot.w); - keyframes.values[v].rotation = rot; - break; - } - case KEYFRAME_TRANSLATION: { - Vec3 trans; - cgltf_accessor_read_float(channel.sampler->output, v, &trans.x, 3); - keyframes.values[v].translation = trans; - break; - } - case KEYFRAME_SCALE: { - Vec3 scale; - cgltf_accessor_read_float(channel.sampler->output, v, &scale.x, 3); - keyframes.values[v].scale = scale; - break; - } - case KEYFRAME_WEIGHTS: { - // TODO: morph weights - break; - } - } - } - sampler.animation.values = keyframes; - sampler.min = channel.sampler->input->min[0]; - sampler.max = channel.sampler->input->max[0]; - - // *target_property = sampler; - printf("%d timestamps between %f and %f\n", sampler.animation.n_timestamps, sampler.min, - sampler.max); - - // TODO: get target - size_t target_index = cgltf_node_index(data, channel.target_node); - size_t joint_index = 0; - bool found = false; - for (u32 ji = 0; ji < main_skeleton.joints->len; ji++) { - if (main_skeleton.joints->data[ji].node_idx == target_index) { - joint_index = ji; - found = true; - break; - } - } - if (!found) { - WARN("Coulndnt find joint index"); - } - sampler.target_joint_idx = - joint_index; // NOTE: this assuming the target is a joint at the moment - AnimationSampler_darray_push(clip.channels, sampler); - } - - AnimationClip_darray_push(out_model->animations, clip); - } - } - - // exit(0); - } - - num_meshes = tmp_meshes->len; - - // we now have an array of meshes, materials, and the material which each mesh should get - out_model->meshes = malloc(num_meshes * sizeof(MeshHandle)); - out_model->mesh_count = num_meshes; - out_model->materials = malloc(num_materials * sizeof(MaterialHandle)); - out_model->material_count = num_materials; - - MaterialHandle* mat_handles = calloc(num_materials, sizeof(MaterialHandle)); - for (u32 mat_i = 0; mat_i < num_materials; mat_i++) { - mat_handles[mat_i] = - Material_pool_insert(Render_GetMaterialPool(), &tmp_materials->data[mat_i]); - } - memcpy(out_model->materials, mat_handles, num_materials * sizeof(MaterialHandle)); - - for (u32 mesh_i = 0; mesh_i < num_meshes; mesh_i++) { - i32 mat_idx = tmp_material_indexes->data[mesh_i]; - if (mat_idx > 0) { - tmp_meshes->data[mesh_i].material = mat_handles[mat_idx]; - - } else { - Material default_mat = PBRMaterialDefault(); - tmp_meshes->data[mesh_i].material = - Material_pool_insert(Render_GetMaterialPool(), &default_mat); - } - MeshHandle mesh = Mesh_pool_insert(Render_GetMeshPool(), &tmp_meshes->data[mesh_i]); - out_model->meshes[mesh_i] = mesh; - } - - free(mat_handles); - - return true; -} - -const char* bool_yes_no(bool pred) { return pred ? "Yes" : "No"; } - -// Loads all materials -size_t GLTF_LoadMaterials(cgltf_data* data, Str8 relative_path, Material_darray* out_materials) { - size_t num_materials = data->materials_count; - TRACE("Num materials %d", num_materials); - for (size_t m = 0; m < num_materials; m++) { - cgltf_material gltf_material = data->materials[m]; - TRACE("Loading material '%s'", gltf_material.name); - cgltf_pbr_metallic_roughness pbr = gltf_material.pbr_metallic_roughness; - - Material our_material = PBRMaterialDefault(); // focusing on PBR materials for now - - our_material.base_colour = - vec3(pbr.base_color_factor[0], pbr.base_color_factor[1], pbr.base_color_factor[2]); - our_material.metallic = pbr.metallic_factor; - our_material.roughness = pbr.roughness_factor; - - // -- albedo / base colour - cgltf_texture_view albedo_tex_view = pbr.base_color_texture; - bool has_albedo_texture = albedo_tex_view.texture != NULL; - TRACE("Has PBR base colour texture? %s", bool_yes_no(has_albedo_texture)); - printf("Base colour factor: %f %f %f\n", pbr.base_color_factor[0], pbr.base_color_factor[1], - pbr.base_color_factor[2]); - if (has_albedo_texture) { - char albedo_map_path[1024]; - snprintf(albedo_map_path, sizeof(albedo_map_path), "%s/%s", relative_path.buf, - albedo_tex_view.texture->image->uri); - our_material.albedo_map = TextureLoadFromFile(albedo_map_path); - } else { - our_material.albedo_map = Render_GetWhiteTexture(); - WARN("GLTF model has no albedo map"); - our_material.base_colour = - vec3_create(pbr.base_color_factor[0], pbr.base_color_factor[1], pbr.base_color_factor[2]); - } - - // -- metallic - cgltf_texture_view metal_rough_tex_view = pbr.metallic_roughness_texture; - printf("Metal factor: %f\n", pbr.metallic_factor); - printf("Roughness factor: %f\n", pbr.roughness_factor); - if (metal_rough_tex_view.texture != NULL) { - char metal_rough_map_path[1024]; - snprintf(metal_rough_map_path, sizeof(metal_rough_map_path), "%s/%s", relative_path.buf, - metal_rough_tex_view.texture->image->uri); - our_material.metallic_roughness_map = TextureLoadFromFile(metal_rough_map_path); - } else { - WARN("GLTF model has no metal/roughness map"); - our_material.metallic = pbr.metallic_factor; - our_material.roughness = pbr.roughness_factor; - } - - cgltf_texture_view normal_tex_view = gltf_material.normal_texture; - if (normal_tex_view.texture != NULL) { - char normal_map_path[1024]; - snprintf(normal_map_path, sizeof(normal_map_path), "%s/%s", relative_path.buf, - normal_tex_view.texture->image->uri); - our_material.normal_map = TextureLoadFromFile(normal_map_path); - } else { - WARN("GLTF model has no normal map"); - } - - u32 string_length = strlen(gltf_material.name) + 1; - assert(string_length < 64); - strcpy(our_material.name, gltf_material.name); - - Material_darray_push(out_materials, our_material); - } - - return out_materials->len; -} diff --git a/src/resources/loaders.h b/src/resources/loaders.h deleted file mode 100644 index ea1f9a2..0000000 --- a/src/resources/loaders.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "defines.h" -#include "render_types.h" -#include "str.h" - -// --- Public API -PUB ModelHandle ModelLoad_obj(const char* path, bool invert_texture_y); -PUB ModelHandle ModelLoad_gltf(const char* path, bool invert_texture_y); - -typedef struct GLTF_LoadStats { - u32 mesh_count, material_count, vertex_count, index_count, animation_count, joint_count; -} GLTF_LoadStats; - -// --- Internal -bool model_load_gltf_str(const char* file_string, const char* filepath, Str8 relative_path, - Model* out_model, bool invert_textures_y); diff --git a/src/resources/obj.c b/src/resources/obj.c deleted file mode 100644 index a5e9b18..0000000 --- a/src/resources/obj.c +++ /dev/null @@ -1,398 +0,0 @@ -/** - * @file obj.c - * @brief Wavefront OBJ loader. - * @copyright Copyright (c) 2024 - */ -#include <ctype.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "core.h" -#include "darray.h" -#include "file.h" -#include "log.h" -#include "maths.h" -#include "mem.h" -#include "platform.h" -#include "render.h" -#include "render_types.h" -#include "str.h" - -extern Core g_core; - -struct face { - u32 vertex_indices[3]; - u32 normal_indices[3]; - u32 uv_indices[3]; -}; -typedef struct face face; - -KITC_DECL_TYPED_ARRAY(Vec3) -KITC_DECL_TYPED_ARRAY(Vec2) -KITC_DECL_TYPED_ARRAY(face) - -// Forward declarations -// void create_submesh(mesh_darray *meshes, Vec3_darray *tmp_positions, Vec3_darray *tmp_normals, -// Vec2_darray *tmp_uvs, face_darray *tmp_faces, material_darray *materials, -// bool material_loaded, char current_material_name[256]); -// bool load_material_lib(const char *path, str8 relative_path, material_darray *materials); -// bool model_load_obj_str(const char *file_string, str8 relative_path, Model *out_model, -// bool invert_textures_y); - -ModelHandle model_load_obj(Core* core, const char* path, bool invert_textures_y) { - size_t arena_size = 1024; - arena scratch = arena_create(malloc(arena_size), arena_size); - - TRACE("Loading model at Path %s\n", path); - path_opt relative_path = path_parent(&scratch, path); - if (!relative_path.has_value) { - WARN("Couldnt get a relative path for the path to use for loading materials & textures later"); - } - const char* file_string = string_from_file(path); - - ModelHandle handle; - // model *model = model_pool_alloc(&g_core.models, &handle); - // model->name = str8_cstr_view(path); - // model->meshes = mesh_darray_new(1); - - // bool success = model_load_obj_str(file_string, relative_path.path, &model, invert_textures_y); - - // if (!success) { - // FATAL("Couldnt load OBJ file at path %s", path); - // ERROR_EXIT("Load fails are considered crash-worthy right now. This will change later.\n"); - // } - - // arena_free_all(&scratch); - // arena_free_storage(&scratch); - return handle; -} - -bool model_load_obj_str(const char* file_string, Str8 relative_path, Model* out_model, - bool invert_textures_y) { - TRACE("Load OBJ from string"); - - // // Setup temps - // vec3_darray *tmp_positions = vec3_darray_new(1000); - // vec3_darray *tmp_normals = vec3_darray_new(1000); - // vec2_darray *tmp_uvs = vec2_darray_new(1000); - // face_darray *tmp_faces = face_darray_new(1000); - // // TODO: In the future I'd like these temporary arrays to be allocated from an arena provided - // // by the function one level up, model_load_obj. That way we can just `return false;` anywhere - // in - // // this code to indicate an error, and be sure that all that memory will be cleaned up without - // // having to call vec3_darray_free in every single error case before returning. - - // // Other state - // bool object_set = false; - // bool material_loaded = false; - // char current_material_name[64]; - - // char *pch; - // char *rest = file_string; - // pch = strtok_r((char *)file_string, "\n", &rest); - - // int line_num = 0; - // char last_char_type = 'a'; - - // while (pch != NULL) { - // line_num++; - // char line_header[128]; - // int offset = 0; - - // // skip whitespace - // char *p = pch; - - // skip_space(pch); - - // if (*p == '\0') { - // /* the string is empty */ - // } else { - // // read the first word of the line - // int res = sscanf(pch, "%s %n", line_header, &offset); - // /* printf("header: %s, offset : %d res: %d\n",line_header, offset, res); */ - // if (res != 1) { - // break; - // } - - // if (strcmp(line_header, "o") == 0 || strcmp(line_header, "g") == 0) { - // // if we're currently parsing one - // if (!object_set) { - // object_set = true; - // } else { - // create_submesh(out_model->meshes, tmp_positions, tmp_normals, tmp_uvs, tmp_faces, - // NULL, // out_model->materials, - // material_loaded, current_material_name); - // object_set = false; - // } - // } else if (strcmp(line_header, "v") == 0) { - // // special logic: if we went from faces back to vertices trigger a mesh output. - // // PS: I hate OBJ - // if (last_char_type == 'f') { - // create_submesh(out_model->meshes, tmp_positions, tmp_normals, tmp_uvs, tmp_faces, - // NULL, // FIXME: out_model->materials, - // material_loaded, current_material_name); - // object_set = false; - // } - - // last_char_type = 'v'; - // vec3 vertex; - // sscanf(pch + offset, "%f %f %f", &vertex.x, &vertex.y, &vertex.z); - - // vec3_darray_push(tmp_positions, vertex); - // } else if (strcmp(line_header, "vt") == 0) { - // last_char_type = 't'; - // vec2 uv; - // char copy[1024]; - // memcpy(copy, pch + offset, strlen(pch + offset) + 1); - // char *p = pch + offset; - // while (isspace((unsigned char)*p)) ++p; - - // // I can't remember what is going on here - // memset(copy, 0, 1024); - // memcpy(copy, pch + offset, strlen(pch + offset) + 1); - // int res = sscanf(copy, "%f %f", &uv.x, &uv.y); - // memset(copy, 0, 1024); - // memcpy(copy, pch + offset, strlen(pch + offset) + 1); - // if (res != 1) { - // // da frick? some .obj files have 3 uvs instead of 2 - // f32 dummy; - // int res2 = sscanf(copy, "%f %f %f", &uv.x, &uv.y, &dummy); - // } - - // if (invert_textures_y) { - // uv.y = -uv.y; // flip Y axis to be consistent with how other PNGs are being handled - // // `texture_load` will flip it again - // } - // vec2_darray_push(tmp_uvs, uv); - // } else if (strcmp(line_header, "vn") == 0) { - // last_char_type = 'n'; - // vec3 normal; - // sscanf(pch + offset, "%f %f %f", &normal.x, &normal.y, &normal.z); - // vec3_darray_push(tmp_normals, normal); - // } else if (strcmp(line_header, "f") == 0) { - // last_char_type = 'f'; - // struct face f; - // sscanf(pch + offset, "%d/%d/%d %d/%d/%d %d/%d/%d", &f.vertex_indices[0], - // &f.uv_indices[0], - // &f.normal_indices[0], &f.vertex_indices[1], &f.uv_indices[1], - // &f.normal_indices[1], &f.vertex_indices[2], &f.uv_indices[2], - // &f.normal_indices[2]); - // // printf("f %d/%d/%d %d/%d/%d %d/%d/%d\n", f.vertex_indices[0], f.uv_indices[0], - // // f.normal_indices[0], - // // f.vertex_indices[1], f.uv_indices[1], f.normal_indices[1], - // // f.vertex_indices[2], f.uv_indices[2], f.normal_indices[2]); - // face_darray_push(tmp_faces, f); - // } else if (strcmp(line_header, "mtllib") == 0) { - // char filename[1024]; - // sscanf(pch + offset, "%s", filename); - // char mtllib_path[1024]; - // snprintf(mtllib_path, sizeof(mtllib_path), "%s/%s", relative_path.buf, filename); - // if (!load_material_lib(mtllib_path, relative_path, out_model->materials)) { - // ERROR("couldnt load material lib"); - // return false; - // } - // } else if (strcmp(line_header, "usemtl") == 0) { - // material_loaded = true; - // sscanf(pch + offset, "%s", current_material_name); - // } - // } - - // pch = strtok_r(NULL, "\n", &rest); - // } - - // // last mesh or if one wasnt created with 'o' directive - // if (face_darray_len(tmp_faces) > 0) { - // TRACE("Last leftover mesh"); - // create_submesh(out_model->meshes, tmp_positions, tmp_normals, tmp_uvs, tmp_faces, - // NULL, // TODO: out_model->materials, - // material_loaded, current_material_name); - // } - - // // Free data - // free((char *)file_string); - // vec3_darray_free(tmp_positions); - // vec3_darray_free(tmp_normals); - // vec2_darray_free(tmp_uvs); - // face_darray_free(tmp_faces); - // TRACE("Freed temporary OBJ loading data"); - - // if (mesh_darray_len(out_model->meshes) > 256) { - // printf("num meshes: %ld\n", mesh_darray_len(out_model->meshes)); - // } - - // // TODO: bounding box calculation for each mesh - // // TODO: bounding box calculation for model - - // TODO: copy from mesh_darray to malloc'd mesh* array - - return true; -} - -// /** -// * @brief Takes the current positions, normals, uvs arrays and constructs the vertex array -// * from those indices. -// */ -// void create_submesh(mesh_darray *meshes, vec3_darray *tmp_positions, vec3_darray *tmp_normals, -// vec2_darray *tmp_uvs, face_darray *tmp_faces, material_darray *materials, -// bool material_loaded, char current_material_name[256]) { -// // size_t num_verts = face_darray_len(tmp_faces) * 3; -// // vertex_darray *out_vertices = vertex_darray_new(num_verts); - -// // face_darray_iter face_iter = face_darray_iter_new(tmp_faces); -// // struct face *f; - -// // while ((f = face_darray_iter_next(&face_iter))) { -// // for (int j = 0; j < 3; j++) { -// // vertex vert = { 0 }; -// // vert.position = tmp_positions->data[f->vertex_indices[j] - 1]; -// // if (vec3_darray_len(tmp_normals) == 0) { -// // vert.normal = vec3_create(0.0, 0.0, 0.0); -// // } else { -// // vert.normal = tmp_normals->data[f->normal_indices[j] - 1]; -// // } -// // vert.uv = tmp_uvs->data[f->uv_indices[j] - 1]; -// // vertex_darray_push(out_vertices, vert); -// // } -// // } - -// // DEBUG("Loaded submesh\n vertices: %zu\n uvs: %zu\n normals: %zu\n faces: %zu", -// // vec3_darray_len(tmp_positions), vec2_darray_len(tmp_uvs), -// vec3_darray_len(tmp_normals), -// // face_darray_len(tmp_faces)); - -// // // Clear current object faces -// // face_darray_clear(tmp_faces); - -// // mesh m = { .vertices = out_vertices }; -// // if (material_loaded) { -// // // linear scan to find material -// // bool found = false; -// // DEBUG("Num of materials : %ld", material_darray_len(materials)); -// // material_darray_iter mat_iter = material_darray_iter_new(materials); -// // blinn_phong_material *cur_material; -// // while ((cur_material = material_darray_iter_next(&mat_iter))) { -// // if (strcmp(cur_material->name, current_material_name) == 0) { -// // DEBUG("Found match"); -// // m.material_index = mat_iter.current_idx - 1; -// // found = true; -// // break; -// // } -// // } - -// // if (!found) { -// // // TODO: default material -// // m.material_index = 0; -// // DEBUG("Set default material"); -// // } -// // } -// // mesh_darray_push(meshes, m); -// } - -// bool load_material_lib(const char *path, str8 relative_path, material_darray *materials) { -// TRACE("BEGIN load material lib at %s", path); - -// // const char *file_string = string_from_file(path); -// // if (file_string == NULL) { -// // ERROR("couldnt load %s", path); -// // return false; -// // } - -// // char *pch; -// // char *saveptr; -// // pch = strtok_r((char *)file_string, "\n", &saveptr); - -// // material current_material = DEFAULT_MATERIAL; - -// // bool material_set = false; - -// // while (pch != NULL) { -// // char line_header[128]; -// // int offset = 0; -// // // read the first word of the line -// // int res = sscanf(pch, "%s %n", line_header, &offset); -// // if (res != 1) { -// // break; -// // } - -// // // When we see "newmtl", start a new material, or flush the previous one -// // if (strcmp(line_header, "newmtl") == 0) { -// // if (material_set) { -// // // a material was being parsed, so flush that one and start a new one -// // material_darray_push(materials, current_material); -// // DEBUG("pushed material with name %s", current_material.name); -// // WARN("Reset current material"); -// // current_material = DEFAULT_MATERIAL; -// // } else { -// // material_set = true; -// // } -// // // scan the new material name -// // char material_name[64]; -// // sscanf(pch + offset, "%s", current_material.name); -// // DEBUG("material name %s\n", current_material.name); -// // // current_material.name = material_name; -// // } else if (strcmp(line_header, "Ka") == 0) { -// // // ambient -// // sscanf(pch + offset, "%f %f %f", ¤t_material.ambient_colour.x, -// // ¤t_material.ambient_colour.y, ¤t_material.ambient_colour.z); -// // } else if (strcmp(line_header, "Kd") == 0) { -// // // diffuse -// // sscanf(pch + offset, "%f %f %f", ¤t_material.diffuse.x, -// ¤t_material.diffuse.y, -// // ¤t_material.diffuse.z); -// // } else if (strcmp(line_header, "Ks") == 0) { -// // // specular -// // sscanf(pch + offset, "%f %f %f", ¤t_material.specular.x, -// // ¤t_material.specular.y, -// // ¤t_material.specular.z); -// // } else if (strcmp(line_header, "Ns") == 0) { -// // // specular exponent -// // sscanf(pch + offset, "%f", ¤t_material.spec_exponent); -// // } else if (strcmp(line_header, "map_Kd") == 0) { -// // char diffuse_map_filename[1024]; -// // sscanf(pch + offset, "%s", diffuse_map_filename); -// // char diffuse_map_path[1024]; -// // snprintf(diffuse_map_path, sizeof(diffuse_map_path), "%s/%s", relative_path.buf, -// // diffuse_map_filename); -// // printf("load from %s\n", diffuse_map_path); - -// // // -------------- -// // texture diffuse_texture = texture_data_load(diffuse_map_path, true); -// // current_material.diffuse_texture = diffuse_texture; -// // strcpy(current_material.diffuse_tex_path, diffuse_map_path); -// // texture_data_upload(¤t_material.diffuse_texture); -// // // -------------- -// // } else if (strcmp(line_header, "map_Ks") == 0) { -// // // char specular_map_path[1024] = "assets/"; -// // // sscanf(pch + offset, "%s", specular_map_path + 7); -// // char specular_map_filename[1024]; -// // sscanf(pch + offset, "%s", specular_map_filename); -// // char specular_map_path[1024]; -// // snprintf(specular_map_path, sizeof(specular_map_path), "%s/%s", relative_path.buf, -// // specular_map_filename); -// // printf("load from %s\n", specular_map_path); -// // // -------------- -// // texture specular_texture = texture_data_load(specular_map_path, true); -// // current_material.specular_texture = specular_texture; -// // strcpy(current_material.specular_tex_path, specular_map_path); -// // texture_data_upload(¤t_material.specular_texture); -// // // -------------- -// // } else if (strcmp(line_header, "map_Bump") == 0) { -// // // TODO -// // } - -// // pch = strtok_r(NULL, "\n", &saveptr); -// // } - -// // TRACE("end load material lib"); - -// // // last mesh or if one wasnt created with 'o' directive -// // // TRACE("Last leftover material"); -// // material_darray_push(materials, current_material); - -// // INFO("Loaded %ld materials", material_darray_len(materials)); -// TRACE("END load material lib"); -// return true; -// } diff --git a/src/std/buf.h b/src/std/buf.h deleted file mode 100644 index 77fc7b9..0000000 --- a/src/std/buf.h +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @file buf.h - * @brief - */ -#pragma once -#include "defines.h" - -typedef struct bytebuffer { - u8* buf; - size_t size; -} bytebuffer; diff --git a/src/std/containers/container_utils.h b/src/std/containers/container_utils.h deleted file mode 100644 index e1d164c..0000000 --- a/src/std/containers/container_utils.h +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @file container_utils.h - * @author your name (you@domain.com) - * @brief - * @version 0.1 - * @date 2024-06-19 - * - * @copyright Copyright (c) 2024 - * - */ - -#pragma once - -typedef struct generic_iterator { -} generic_iterator; - -typedef void* (*iterator_next_item)(void* iterator);
\ No newline at end of file diff --git a/src/std/containers/darray.h b/src/std/containers/darray.h deleted file mode 100644 index 080afb4..0000000 --- a/src/std/containers/darray.h +++ /dev/null @@ -1,151 +0,0 @@ -/** - * @file darray.h - * @brief Typed dynamic array - * @copyright Copyright (c) 2023 - */ -// COPIED FROM KITC WITH SOME MINOR ADJUSTMENTS - -/* TODO: - - a 'find' function that takes a predicate (maybe wrap with a macro so we dont have to define a - new function?) -*/ - -#ifndef KITC_TYPED_ARRAY_H -#define KITC_TYPED_ARRAY_H - -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#define DARRAY_DEFAULT_CAPACITY 64 -#define DARRAY_RESIZE_FACTOR 3 - -/** @brief create a new darray type and functions with type `N` */ -#define typed_array(T) \ - struct { \ - /* @brief current number of items in the array */ \ - size_t len; \ - size_t capacity; \ - T* data; \ - } - -#define typed_array_iterator(T) \ - struct { \ - T##_darray* array; \ - size_t current_idx; \ - } - -#define PREFIX static - -#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 Type##_darray* Type##_darray_new(size_t starting_capacity) { \ - Type##_darray* d; \ - T* data; \ - d = malloc(sizeof(Type##_darray)); \ - data = malloc(starting_capacity * sizeof(T)); \ - \ - d->len = 0; \ - d->capacity = starting_capacity; \ - d->data = data; \ - \ - return d; \ - } \ - \ - PREFIX void Type##_darray_free(Type##_darray* d) { \ - if (d != NULL) { \ - free(d->data); \ - free(d); \ - } \ - } \ - \ - 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 */ \ - \ - d->capacity = capacity; \ - d->data = new_data; \ - return new_data; \ - } \ - \ - 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 = Type##_darray_resize(d, new_capacity); \ - (void)resized; \ - } \ - \ - d->data[d->len] = value; \ - d->len += 1; \ - } \ - \ - 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 = Type##_darray_resize(d, new_capacity); \ - (void)resized; \ - } \ - \ - T* place = d->data + d->len; \ - d->len += 1; \ - memcpy(place, value, sizeof(T)); \ - } \ - \ - 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 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 = Type##_darray_resize(d, new_capacity); \ - (void)resized; \ - } \ - \ - /* shift existing data after index */ \ - T* insert_dest = d->data + index; \ - T* shift_dest = insert_dest + 1; \ - \ - int num_items = d->len - index; \ - \ - d->len += 1; \ - memcpy(shift_dest, insert_dest, num_items * sizeof(T)); \ - memcpy(insert_dest, value, sizeof(T)); \ - } \ - \ - PREFIX void Type##_darray_clear(Type##_darray* d) { \ - d->len = 0; \ - memset(d->data, 0, d->capacity * sizeof(T)); \ - } \ - \ - PREFIX size_t Type##_darray_len(Type##_darray* d) { return d->len; } \ - \ - 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* Type##_darray_iter_next(Type##_darray_iter* iterator) { \ - if (iterator->current_idx < iterator->array->len) { \ - return &iterator->array->data[iterator->current_idx++]; \ - } else { \ - return NULL; \ - } \ - } - -#endif // KITC_TYPED_ARRAY_H diff --git a/src/std/containers/graphs.h b/src/std/containers/graphs.h deleted file mode 100644 index 5dbec97..0000000 --- a/src/std/containers/graphs.h +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @file graphs.h - * @author your name (you@domain.com) - * @brief - * @version 0.1 - * @date 2024-04-27 - * - * @copyright Copyright (c) 2024 - * - */ - -// Adjacency list backed graphs - -// Matrix backed graphs (not as useful)
\ No newline at end of file diff --git a/src/std/containers/hashmap.h b/src/std/containers/hashmap.h deleted file mode 100644 index 95c1c6b..0000000 --- a/src/std/containers/hashmap.h +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @file hashmap.h - * @author your name (you@domain.com) - * @brief - * @version 0.1 - * @date 2024-04-27 - * - * @copyright Copyright (c) 2024 - * - */ - -typedef struct hashmap hashmap; - -/* -Example usage -------------- -init hashmap -insert (string, material) -get (string) -> material_opt or material* ? - -*/ - -void hashmap_init(hashmap* map); - -// ... - -void hashmap_free(hashmap* map);
\ No newline at end of file diff --git a/src/std/containers/hashset.h b/src/std/containers/hashset.h deleted file mode 100644 index 7f87213..0000000 --- a/src/std/containers/hashset.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @file hashset.h - * @author your name (you@domain.com) - * @brief - * @version 0.1 - * @date 2024-04-27 - * - * @copyright Copyright (c) 2024 - * - */ - -#include "defines.h" - -typedef struct hashset hashset; - -/** @brief Describes a function that will take a pointer to a datatype (e.g. a u64 or a struct) - and return a hashed key. */ -typedef uint64_t (*hash_item)(void* item); - -void hashset_init(hashset* set, hash_item hash_func, size_t initial_capacity); -// TODO: void hashset_from_iterator(); -bool hashset_insert(hashset* set, void* item, uint64_t* out_key); -void hashset_batch_insert(hashset* set, void* items, u64 item_count); -bool hashset_contains(hashset* set, void* item); -bool hashset_remove_item(hashset* set, void* item); -bool hashset_remove_key(hashset* set, uint64_t key); -void hashset_merge(hashset* set_a, hashset* set_b); -hashset* hashset_merge_cloned(hashset* set_a, hashset* set_b); -void hashset_free(hashset* set);
\ No newline at end of file diff --git a/src/std/containers/ring_queue.c b/src/std/containers/ring_queue.c deleted file mode 100644 index 8bfc10b..0000000 --- a/src/std/containers/ring_queue.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "ring_queue.h" - -#include <stdlib.h> -#include <string.h> -#include "defines.h" - -ring_queue* ring_queue_new(size_t type_size, size_t capacity, void* memory) { - ring_queue* q = malloc(sizeof(ring_queue)); - q->len = 0; - q->capacity = capacity; - q->type_size = type_size; - q->head = 0; - q->tail = -1; - - if (memory) { - // caller owns the memory - q->owns_memory = false; - q->data = memory; - } else { - // ring queue should own the memory - q->owns_memory = true; - q->data = malloc(capacity * type_size); - } - - return q; -} - -void ring_queue_free(ring_queue* queue) { - if (queue) { - if (queue->owns_memory) { - free(queue->data); - } - free(queue); - } -} - -bool ring_queue_enqueue(ring_queue* queue, const void* value) { - if (queue->len == queue->capacity) { - return false; - } - - queue->tail = (queue->tail + 1) % queue->capacity; - memcpy(queue->data + (queue->tail * queue->type_size), value, queue->type_size); - queue->len++; - return true; -} - -bool ring_queue_dequeue(ring_queue* queue, void* out_value) { - if (queue->len == 0) { - // queue is empty - return false; - } - - memcpy(out_value, queue->data + (queue->head * queue->type_size), queue->type_size); - queue->head = (queue->head + 1) % queue->capacity; - queue->len--; - return true; -} - -bool ring_queue_peek(const ring_queue* queue, void* out_value) { - if (queue->len == 0) { - // queue is empty - return false; - } - - memcpy(out_value, queue->data + (queue->head * queue->type_size), queue->type_size); - return true; -}
\ No newline at end of file diff --git a/src/std/containers/ring_queue.h b/src/std/containers/ring_queue.h deleted file mode 100644 index 15d5da4..0000000 --- a/src/std/containers/ring_queue.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @file ring_queue.h - * @author your name (you@domain.com) - * @brief - * @version 0.1 - * @date 2024-02-24 - * - * @copyright Copyright (c) 2024 - * - */ -#pragma once -#include "defines.h" - -/** - * @brief a fixed-size ring queue - */ -typedef struct ring_queue { - size_t len; - size_t capacity; - size_t type_size; - void* data; - bool owns_memory; - int32_t head; - int32_t tail; -} ring_queue; - -ring_queue* ring_queue_new(size_t type_size, size_t capacity, void* memory_block); - -void ring_queue_free(ring_queue* queue); - -bool ring_queue_enqueue(ring_queue* queue, const void* value); - -bool ring_queue_dequeue(ring_queue* queue, void* out_value); - -bool ring_queue_peek(const ring_queue* queue, void* out_value);
\ No newline at end of file diff --git a/src/std/containers/stack_array.h b/src/std/containers/stack_array.h deleted file mode 100644 index d2b6bdd..0000000 --- a/src/std/containers/stack_array.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include <stdbool.h> - -// Defines "_sarray" types - -#define TYPED_STACK_ARRAY(T, Name, Len) \ - typedef struct Name##_sarray { \ - T items[ Len ]; \ - size_t len; \ - } Name##_sarray; \ - Name##_sarray Name##_sarray_create() { \ - Name##_sarray arr = { .len = 0 }; \ - return arr; \ - } \ - bool Name##_sarray_push(Name##_sarray* arr, T item) { \ - if (arr->len == Len) { return false; }\ - arr->items[arr->len++] = item;\ - return true;\ - } diff --git a/src/std/mem.c b/src/std/mem.c deleted file mode 100644 index 1f9078b..0000000 --- a/src/std/mem.c +++ /dev/null @@ -1,135 +0,0 @@ -#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*)) -#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; - // TRACE("Padding %td available %td", padding, available); - if (available < 0 || (ptrdiff_t)size > available) { - ERROR_EXIT("Arena ran out of memory\n"); - } - void* p = a->curr + padding; - a->curr += padding + size; - return memset(p, 0, size); -} -void* arena_alloc(arena* a, size_t size) { return arena_alloc_align(a, size, DEFAULT_ALIGNMENT); } - -arena arena_create(void* backing_buffer, size_t capacity) { - return (arena){ .begin = backing_buffer, - .curr = backing_buffer, - .end = backing_buffer + (ptrdiff_t)capacity }; -} - -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); } - -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; } - -// --- Pool - -void_pool void_pool_create(arena* a, const char* debug_label, u64 capacity, u64 entry_size) { - size_t memory_requirements = capacity * entry_size; - void* backing_buf = arena_alloc(a, memory_requirements); - - assert(entry_size >= sizeof(void_pool_header)); // TODO: create my own assert with error message - - void_pool pool = { .capacity = capacity, - .entry_size = entry_size, - .count = 0, - .backing_buffer = backing_buf, - .free_list_head = NULL, - .debug_label = debug_label }; - - void_pool_free_all(&pool); - - 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("%s Pool is full (head = null)", pool->debug_label); - 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--; -} - -u32 void_pool_insert(void_pool* pool, void* item) { - u32 raw_handle; - void* item_dest = void_pool_alloc(pool, &raw_handle); - memcpy(item_dest, item, pool->entry_size); - return raw_handle; -} diff --git a/src/std/mem.h b/src/std/mem.h deleted file mode 100644 index 56c1230..0000000 --- a/src/std/mem.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - * @file mem.h - * @brief Allocators, memory tracking - * @version 0.1 - * @date 2024-02-24 - * - * @copyright Copyright (c) 2024 - * - */ -#pragma once - -#include <stddef.h> -#include "defines.h" - -typedef void* (*alloc_fn)(size_t size); -typedef void (*free_fn)(void* ptr); - -typedef struct allocator_t { - alloc_fn alloc; - free_fn free; -} allocator_t; - -// --- Arena - -// Inspired by https://nullprogram.com/blog/2023/09/27/ -typedef struct arena { - char* begin; - char* curr; - 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 - -// --- 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; - const char* debug_label; -} void_pool; - -void_pool void_pool_create(arena* a, const char* debug_label, 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(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); -u32 void_pool_insert(void_pool* pool, void* item); -// TODO: fn to dealloc from the pointer that was handed out - -// 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, "\"" #Name "\"", 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); \ - } \ - static Name##Handle Name##_pool_insert(Name##_pool* pool, T* item) { \ - u32 raw_handle = void_pool_insert(pool, item); \ - return (Name##Handle){ .raw = raw_handle }; \ - } diff --git a/src/std/str.c b/src/std/str.c deleted file mode 100644 index 89c76a0..0000000 --- a/src/std/str.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "str.h" -#include <assert.h> -#include <string.h> -#include "log.h" -#include "mem.h" - -Str8 Str8_create(u8* buf, size_t len) { return (Str8){ .buf = buf, .len = len }; } - -Str8 Str8_cstr_view(char* string) { return Str8_create((u8*)string, strlen(string)); } - -bool Str8_equals(Str8 a, Str8 b) { - if (a.len != b.len) { - return false; - } - - for (size_t i = 0; i < a.len; i++) { - if (a.buf[i] != b.buf[i]) { - return false; - } - } - return true; -} - -char* Str8_to_cstr(arena* a, Str8 s) { - bool is_null_terminated = s.buf[s.len - 1] == 0; - size_t n_bytes = is_null_terminated ? s.len : s.len + 1; - - u8* dest = arena_alloc(a, n_bytes); - - memcpy(dest, s.buf, s.len); - if (is_null_terminated) { - dest[s.len] = '\0'; - } - return (char*)dest; -} - -char* Clone_cstr(arena* a, const char* s) { - if (s == NULL) { - WARN("Tried to clone a NULL char*"); - return NULL; - } - Str8 st = Str8_cstr_view(s); - return Str8_to_cstr(a, st); -} - -Str8 Str8_concat(arena* a, Str8 left, Str8 right) { - size_t n_bytes = left.len + right.len + 1; - - u8* dest = arena_alloc(a, n_bytes); - memcpy(dest, left.buf, left.len); - memcpy(dest + right.len, right.buf, right.len); - - dest[n_bytes - 1] = '\0'; - - return Str8_create(dest, n_bytes); -} - -Str8 Str8_substr(Str8 s, u64 min, u64 max) { - assert(min >= 0); - assert(min < s.len); - assert(max >= 0); - assert(max <= s.len); - uint8_t* start = s.buf + (ptrdiff_t)min; - size_t new_len = max - min; - return (Str8){ .buf = start, .len = new_len }; -} - -Str8 Str8_take(Str8 s, u64 first_n) { return Str8_substr(s, 0, first_n); } - -Str8 Str8_drop(Str8 s, u64 last_n) { return Str8_substr(s, s.len - last_n, s.len); } - -Str8 Str8_skip(Str8 s, u64 n) { return Str8_substr(s, n, s.len); } - -Str8 Str8_chop(Str8 s, u64 n) { return Str8_substr(s, 0, s.len - n); } diff --git a/src/std/str.h b/src/std/str.h deleted file mode 100644 index a29bf9a..0000000 --- a/src/std/str.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @file str.h - * @author your name (you@domain.com) - * @brief - * @version 0.1 - * @date 2024-02-25 - * - * @copyright Copyright (c) 2024 - * - */ -#pragma once - -#include <ctype.h> - -#include "defines.h" -#include "mem.h" - -/** - * @brief Fat pointer representing a UTF8 (TODO some APIs supporting utf8) encoded string - * @note when using `printf` you must use %s.*s length, string until our own modified - print routines are written. alternatively wrap in `cstr()` and pass to `%s`. - */ -typedef struct { - u8* buf; - size_t len; -} Str8; - -// --- Constructors - -/** @brief Take a string literal and turn it into a `str8` */ -#define str8(s) \ - (Str8) { (u8*)s, ((sizeof(s) / sizeof(*(s)) - 1)) } - -Str8 Str8_create(u8* buf, size_t len); - -// TODO: Str8_OntoArena(arena* a, Str8 s); - -/** @brief Return a null-terminated C string cloned onto an arena */ -char* Str8_to_cstr(arena* a, Str8 s); - -#define cstr(a, s) (Str8_to_cstr(a, s)) // Shorthand - -/** @brief Return a Str8 that references a statically allocated string. - `string` therefore must already be null-terminated. - @note The backing `string` cannot be modified. */ -Str8 Str8_cstr_view(char* string); - -char* Clone_cstr(arena* a, const char* s); - -// --- Comparisons - -/** @brief Compare two strings for exact equality */ -bool Str8_equals(Str8 a, Str8 b); - -/** - * @brief Compare the first `first_nchars` of each string for equality - * @details If either of the strings are shorter than the number only the characters up until the - end of the shorter string will be compared. - * @returns 0 if they are fully equal up until `first_nchars`, i.e they never differed, else it - returns the index at which the first string differed from the second string. -*/ -size_t Str8_nequals(Str8 a, Str8 b, size_t first_nchars); - -bool Str8_ends_with(Str8 input_str, Str8 suffix); - -/// --- Subviews - -Str8 Str8_substr(Str8 s, u64 min, u64 max); -/** @brief Keeps only the `first_n` chars of `s` */ -Str8 Str8_take(Str8 s, u64 first_n); -/** @brief Keeps only the `last_n` chars of `s` */ -Str8 Str8_drop(Str8 s, u64 last_n); -/** @brief Keeps everything after the first `n` chars of `s` */ -Str8 Str8_skip(Str8 s, u64 n); -/** @brief Keeps everything before the last `n` chars of `s` */ -Str8 Str8_chop(Str8 s, u64 n); - -Str8 Str8_concat(arena* a, Str8 left, Str8 right); - -/// --- Misc - -static inline bool Str8_is_null_term(Str8 a) { - return a.buf[a.len] == 0; // This doesn't seem safe. YOLO -} - -// TODO: move or delete this and replace with handling using our internal type -static void skip_space(char* p) { - while (isspace((unsigned char)*p)) ++p; -} diff --git a/src/std/utils.h b/src/std/utils.h deleted file mode 100644 index c9827a3..0000000 --- a/src/std/utils.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include <stdbool.h> - -const char* bool_str(bool input) { return input ? "True" : "False"; }
\ No newline at end of file diff --git a/src/systems/grid.c b/src/systems/grid.c deleted file mode 100644 index e907865..0000000 --- a/src/systems/grid.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "grid.h" -#include "file.h" -#include "log.h" -#include "maths.h" -#include "maths_types.h" -#include "primitives.h" -#include "ral_common.h" -#include "ral_impl.h" -#include "ral_types.h" -#include "render.h" -#include "render_types.h" -#include "shader_layouts.h" - -void Grid_Init(Grid_Storage* storage) { - INFO("Infinite Grid initialisation"); - Geometry plane_geo = Geo_CreatePlane(f32x2(1.0, 1.0), 1, 1); - Mesh plane_mesh = Mesh_Create(&plane_geo, true); - storage->plane_vertices = plane_mesh.vertex_buffer; - - u32 indices[6] = { 5, 4, 3, 2, 1, 0 }; - storage->plane_indices = - GPU_BufferCreate(6 * sizeof(u32), BUFFER_INDEX, BUFFER_FLAG_GPU, &indices); - - GPU_RenderpassDesc rpass_desc = { - .default_framebuffer = true, - }; - storage->renderpass = GPU_Renderpass_Create(rpass_desc); - - arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); - - Str8 vert_path = str8("assets/shaders/grid.vert"); - Str8 frag_path = str8("assets/shaders/grid.frag"); - str8_opt vertex_shader = str8_from_file(&scratch, vert_path); - str8_opt fragment_shader = str8_from_file(&scratch, frag_path); - if (!vertex_shader.has_value || !fragment_shader.has_value) { - ERROR_EXIT("Failed to load shaders from disk") - } - - ShaderDataLayout camera_data = Binding_Camera_GetLayout(NULL); - - GraphicsPipelineDesc pipeline_desc = { - .debug_name = "Infinite grid pipeline", - .vertex_desc = static_3d_vertex_description(), - .data_layouts = { camera_data }, - .data_layouts_count = 1, - .vs = { - .debug_name = "Grid vertex shader", - .filepath = vert_path, - .code = vertex_shader.contents, - }, - .fs = { - .debug_name = "Grid fragment shader", - .filepath = frag_path, - .code = fragment_shader.contents, - }, - .wireframe = false, - }; - storage->pipeline = GPU_GraphicsPipeline_Create(pipeline_desc, storage->renderpass); -} - -void Grid_Draw() { - Grid_Storage* grid = Render_GetGridStorage(); - Grid_Execute(grid); -} - -void Grid_Execute(Grid_Storage* storage) { - RenderScene* scene = Render_GetScene(); - GPU_CmdEncoder* enc = GPU_GetDefaultEncoder(); - GPU_CmdEncoder_BeginRender(enc, storage->renderpass); - GPU_EncodeBindPipeline(enc, storage->pipeline); - Mat4 view, proj; - u32x2 dimensions = GPU_Swapchain_GetDimensions(); - Camera camera = scene->camera; - Camera_ViewProj(&camera, (f32)dimensions.x, (f32)dimensions.y, &view, &proj); - Binding_Camera camera_data = { .view = view, - .projection = proj, - .viewPos = vec4(camera.position.x, camera.position.y, - camera.position.z, 1.0) }; - GPU_EncodeBindShaderData(enc, 0, Binding_Camera_GetLayout(&camera_data)); - GPU_EncodeSetVertexBuffer(enc, storage->plane_vertices); - GPU_EncodeSetIndexBuffer(enc, storage->plane_indices); - GPU_EncodeDrawIndexedTris(enc, 6); - GPU_CmdEncoder_EndRender(enc); -} diff --git a/src/systems/grid.h b/src/systems/grid.h deleted file mode 100644 index d8bc567..0000000 --- a/src/systems/grid.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "ral_impl.h" -#include "ral_types.h" - -typedef struct Grid_Storage { - GPU_Renderpass* renderpass; - GPU_Pipeline* pipeline; - BufferHandle plane_vertices; - BufferHandle plane_indices; -} Grid_Storage; - -// --- Public API -PUB void Grid_Init(Grid_Storage* storage); -// void Grid_Shutdown(Grid_Storage* storage); -PUB void Grid_Draw(); - -// --- Internal -void Grid_Execute(Grid_Storage* storage); -// typedef struct GridUniforms {} GridUniforms; -// ShaderDataLayout GridUniforms_GetLayout(void* data);
\ No newline at end of file diff --git a/src/systems/input.c b/src/systems/input.c deleted file mode 100644 index c3af96a..0000000 --- a/src/systems/input.c +++ /dev/null @@ -1,105 +0,0 @@ -#include "input.h" - -#include <assert.h> -#include <glfw3.h> -#include <string.h> - -#include "keys.h" -#include "log.h" - -static Input_State* g_input; // Use a global to simplify caller code - -bool Input_Init(Input_State* input, GLFWwindow* window) { - INFO("Input init"); - memset(input, 0, sizeof(Input_State)); - - input->window = window; - // Set everything to false. Could just set memory to zero but where's the fun in that - for (int i = KEYCODE_SPACE; i < KEYCODE_MAX; i++) { - input->depressed_keys[i] = false; - input->just_pressed_keys[i] = false; - input->just_released_keys[i] = false; - } - - g_input = input; - - assert(input->mouse.x_delta == 0); - assert(input->mouse.y_delta == 0); - - INFO("Finish input init"); - return true; -} - -void Input_Shutdown(Input_State* input) {} - -void Input_Update(Input_State* input) { - glfwPollEvents(); - // --- update keyboard input - - // if we go from un-pressed -> pressed, set as "just pressed" - // if we go from pressed -> un-pressed, set as "just released" - for (int i = KEYCODE_SPACE; i < KEYCODE_MAX; i++) { - bool new_state = false; - if (glfwGetKey(input->window, i) == GLFW_PRESS) { - new_state = true; - } else { - new_state = false; - } - if (!input->depressed_keys[i] == false && new_state) { - input->just_pressed_keys[i] = true; - } else { - input->just_pressed_keys[i] = false; - } - - if (input->depressed_keys[i] && !new_state) { - input->just_released_keys[i] = true; - } else { - input->just_released_keys[i] = false; - } - - input->depressed_keys[i] = new_state; - } - - // --- update mouse input - - // cursor position - f64 current_x, current_y; - glfwGetCursorPos(input->window, ¤t_x, ¤t_y); - i32 quantised_cur_x = (i32)current_x; - i32 quantised_cur_y = (i32)current_y; - - mouse_state new_mouse_state = { 0 }; - new_mouse_state.x = quantised_cur_x; - new_mouse_state.y = quantised_cur_y; - new_mouse_state.x_delta = quantised_cur_x - input->mouse.x; - new_mouse_state.y_delta = quantised_cur_y - input->mouse.y; - - // buttons - int left_state = glfwGetMouseButton(input->window, GLFW_MOUSE_BUTTON_LEFT); - int right_state = glfwGetMouseButton(input->window, GLFW_MOUSE_BUTTON_RIGHT); - - for (int i = 0; i < 3; i++) { - new_mouse_state.prev_pressed_states[i] = input->mouse.cur_pressed_states[i]; - } - new_mouse_state.cur_pressed_states[MOUSEBTN_LEFT] = left_state == GLFW_PRESS; - new_mouse_state.cur_pressed_states[MOUSEBTN_RIGHT] = right_state == GLFW_PRESS; - - // this was dumb! need to also check button state changes lol - // if (new_mouse_state.x != input->mouse.x || new_mouse_state.y != input->mouse.y) - // TRACE("Mouse (x,y) = (%d,%d)", input->mouse.x, input->mouse.y); - - input->mouse = new_mouse_state; -} - -bool key_is_pressed(keycode key) { return g_input->depressed_keys[key]; } - -bool key_just_pressed(keycode key) { return g_input->just_pressed_keys[key]; } - -bool key_just_released(keycode key) { return g_input->just_released_keys[key]; } - -bool MouseBtn_Held(MouseBtn btn) { - assert(btn < 3); - return g_input->mouse.prev_pressed_states[btn] && g_input->mouse.cur_pressed_states[btn]; -} - -mouse_state Input_GetMouseState() { return g_input->mouse; }
\ No newline at end of file diff --git a/src/systems/input.h b/src/systems/input.h deleted file mode 100644 index c3b2500..0000000 --- a/src/systems/input.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @brief - */ -#pragma once - -#include "defines.h" -#include "keys.h" - -struct GLFWWindow; - -typedef enum MouseBtn { - MOUSEBTN_LEFT = 0, - MOUSEBTN_RIGHT = 1, - MOUSEBTN_MIDDLE = 2, -} MouseBtn; - -typedef struct mouse_state { - i32 x; - i32 y; - i32 x_delta; - i32 y_delta; - bool prev_pressed_states[3]; - bool cur_pressed_states[3]; -} mouse_state; - -typedef struct Input_State { - struct GLFWwindow* window; - mouse_state mouse; - bool depressed_keys[KEYCODE_MAX]; - bool just_pressed_keys[KEYCODE_MAX]; - bool just_released_keys[KEYCODE_MAX]; -} Input_State; - -/** @brief `key` is currently being held down */ -PUB bool key_is_pressed(keycode key); - -/** @brief `key` was just pressed */ -PUB bool key_just_pressed(keycode key); - -/** @brief `key` was just released */ -PUB bool key_just_released(keycode key); - -// TODO: right btn as well -PUB bool MouseBtn_Held(MouseBtn btn); - -// --- Lifecycle - -PUB bool Input_Init(Input_State* input, struct GLFWwindow* window); -PUB void Input_Shutdown(Input_State* input); - -PUB void Input_Update(Input_State* state); // must be run once per main loop - -PUB mouse_state Input_GetMouseState();
\ No newline at end of file diff --git a/src/systems/keys.h b/src/systems/keys.h deleted file mode 100644 index 6082a59..0000000 --- a/src/systems/keys.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -typedef enum keycode { - // TODO: add all keycodes - KEYCODE_SPACE = 32, - KEYCODE_APOSTROPHE = 39, - KEYCODE_COMMA = 44, - KEYCODE_MINUS = 45, - KEYCODE_PERIOD = 46, - KEYCODE_SLASH = 47, - KEYCODE_0 = 48, - KEYCODE_1 = 49, - KEYCODE_2 = 50, - KEYCODE_3 = 51, - KEYCODE_4 = 52, - KEYCODE_5 = 53, - KEYCODE_6 = 54, - KEYCODE_7 = 55, - KEYCODE_8 = 56, - KEYCODE_9 = 57, - KEYCODE_SEMICOLON = 59, - KEYCODE_EQUAL = 61, - KEYCODE_A = 65, - KEYCODE_B = 66, - KEYCODE_C = 67, - KEYCODE_D = 68, - KEYCODE_E = 69, - KEYCODE_F = 70, - KEYCODE_G = 71, - KEYCODE_H = 72, - KEYCODE_I = 73, - KEYCODE_J = 74, - KEYCODE_K = 75, - KEYCODE_L = 76, - KEYCODE_M = 77, - KEYCODE_N = 78, - KEYCODE_O = 79, - KEYCODE_P = 80, - KEYCODE_Q = 81, - KEYCODE_R = 82, - KEYCODE_S = 83, - KEYCODE_T = 84, - KEYCODE_U = 85, - KEYCODE_V = 86, - KEYCODE_W = 87, - KEYCODE_X = 88, - KEYCODE_Y = 89, - KEYCODE_Z = 90, - - KEYCODE_ESCAPE = 256, - KEYCODE_ENTER = 257, - KEYCODE_TAB = 258, - KEYCODE_BACKSPACE = 259, - KEYCODE_KEY_RIGHT = 262, - KEYCODE_KEY_LEFT = 263, - KEYCODE_KEY_DOWN = 264, - KEYCODE_KEY_UP = 265, - KEYCODE_MAX = 348 -} keycode; diff --git a/src/systems/screenspace.h b/src/systems/screenspace.h deleted file mode 100644 index 5f0c579..0000000 --- a/src/systems/screenspace.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @brief Drawing shapes for UI or other reasons in screenspace - */ -#pragma once - -#include "colours.h" -#include "darray.h" -#include "defines.h" -#include "render_types.h" - -/** A draw_cmd packet for rendering a rectangle */ -struct draw_rect { - i32 x, y; // signed ints so we can draw things offscreen (e.g. a window half inside the viewport) - u32 width, height; - rgba colour; - // TODO: border colour, gradients -}; - -/** A draw_cmd packet for rendering a circle */ -struct draw_circle { - i32 x, y; - f32 radius; - rgba colour; -}; - -/** @brief Tagged union that represents a UI shape to be drawn. */ -typedef struct draw_cmd { - enum { DRAW_RECT, CIRCLE } draw_cmd_type; - union { - struct draw_rect rect; - struct draw_circle circle; - }; -} draw_cmd; - -KITC_DECL_TYPED_ARRAY(draw_cmd) - -typedef struct screenspace_state { - u32 rect_vbo; - u32 rect_vao; - // shader rect_shader; - draw_cmd_darray* draw_cmd_buf; -} screenspace_state; - -// --- Lifecycle -bool screenspace_2d_init(screenspace_state* state); -void screenspace_2d_shutdown(screenspace_state* state); -/** Drains the draw_cmd buffer and emits draw calls to render each one */ -void screenspace_2d_render(screenspace_state* state); - -struct core; - -/** @brief Draw a rectangle to the screen. (0,0) is the bottom-left */ -void draw_rectangle(struct core* core, rgba colour, i32 x, i32 y, u32 width, u32 height);
\ No newline at end of file diff --git a/src/systems/terrain.c b/src/systems/terrain.c deleted file mode 100644 index 069000e..0000000 --- a/src/systems/terrain.c +++ /dev/null @@ -1,204 +0,0 @@ -/** - * @brief - */ -#include "terrain.h" -#include <assert.h> -#include "file.h" -#include "glad/glad.h" -#include "log.h" -#include "maths.h" -#include "mem.h" -#include "ral_common.h" -#include "ral_impl.h" -#include "ral_types.h" -#include "render.h" -#include "shader_layouts.h" -#include "str.h" - -#define TERRAIN_GRID_U 505 -#define TERRAIN_GRID_V 505 - -bool Terrain_Init(Terrain_Storage* storage) { - storage->grid_dimensions = u32x2(TERRAIN_GRID_U, TERRAIN_GRID_V); - storage->hmap_loaded = false; - - GPU_RenderpassDesc rpass_desc = { - .default_framebuffer = true, - }; - storage->hmap_renderpass = GPU_Renderpass_Create(rpass_desc); - - arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); - - Str8 vert_path = str8("assets/shaders/terrain.vert"); - Str8 frag_path = str8("assets/shaders/terrain.frag"); - str8_opt vertex_shader = str8_from_file(&scratch, vert_path); - str8_opt fragment_shader = str8_from_file(&scratch, frag_path); - if (!vertex_shader.has_value || !fragment_shader.has_value) { - ERROR_EXIT("Failed to load shaders from disk") - } - - ShaderDataLayout camera_data = Binding_Camera_GetLayout(NULL); - ShaderDataLayout terrain_data = TerrainUniforms_GetLayout(NULL); - - GraphicsPipelineDesc pipeline_desc = { - .debug_name = "terrain rendering pipeline", - .vertex_desc = static_3d_vertex_description(), - .data_layouts = { camera_data, terrain_data }, - .data_layouts_count = 2, - .vs = { - .debug_name = "terrain vertex shader", - .filepath = vert_path, - .code = vertex_shader.contents, - }, - .fs = { - .debug_name = "terrain fragment shader", - .filepath = frag_path, - .code = fragment_shader.contents, - }, - .wireframe = false, - }; - storage->hmap_pipeline = GPU_GraphicsPipeline_Create(pipeline_desc, storage->hmap_renderpass); - - storage->texture = TextureLoadFromFile("assets/demo/textures/grass2.png"); - - return true; -} - -void Terrain_Shutdown(Terrain_Storage* storage) {} - -void Terrain_LoadHeightmap(Terrain_Storage* storage, Heightmap hmap, f32 grid_scale, - bool free_on_upload) { - // If there's a current one we will delete it and reallocate buffers - if (storage->hmap_loaded) { - GPU_BufferDestroy(storage->vertex_buffer); - GPU_BufferDestroy(storage->index_buffer); - } - - u32 width = hmap.pixel_dimensions.x; - u32 height = hmap.pixel_dimensions.y; - storage->grid_scale = grid_scale; - - size_t num_vertices = storage->grid_dimensions.x * storage->grid_dimensions.y; - storage->num_vertices = num_vertices; - - Vertex_darray* vertices = Vertex_darray_new(num_vertices); - u32 index = 0; - for (u32 i = 0; i < storage->grid_dimensions.x; i++) { - for (u32 j = 0; j < storage->grid_dimensions.y; j++) { - size_t position = j * storage->grid_dimensions.x + i; - u8* bytes = hmap.image_data; - u8 channel = bytes[position]; - float value = (float)channel / 255.0; - // printf("(%d, %d) %d : %f \n", i, j, channel, value); - - assert(index < num_vertices); - f32 height = Heightmap_HeightXZ(&hmap, i, j); - Vec3 v_pos = vec3_create(i * grid_scale, height, j * grid_scale); - Vec3 v_normal = VEC3_Y; - float tiling_factor = 505.0f; - Vec2 v_uv = vec2((f32)i / width * tiling_factor, (f32)j / height * tiling_factor); - Vertex v = { .static_3d = { .position = v_pos, .normal = v_normal, .tex_coords = v_uv } }; - Vertex_darray_push(vertices, v); - index++; - } - } - BufferHandle vertices_handle = GPU_BufferCreate(num_vertices * sizeof(Vertex), BUFFER_VERTEX, - BUFFER_FLAG_GPU, vertices->data); - storage->vertex_buffer = vertices_handle; - - u32 quad_count = (width - 1) * (height - 1); - u32 indices_count = quad_count * 6; - storage->indices_count = indices_count; - u32_darray* indices = u32_darray_new(indices_count); - for (u32 i = 0; i < (width - 1); i++) { // row - for (u32 j = 0; j < (height - 1); j++) { // col - u32 bot_left = i * width + j; - u32 top_left = (i + 1) * width + j; - u32 top_right = (i + 1) * width + (j + 1); - u32 bot_right = i * width + j + 1; - - // top left tri - u32_darray_push(indices, top_right); - u32_darray_push(indices, top_left); - u32_darray_push(indices, bot_left); - - // bottom right tri - u32_darray_push(indices, bot_right); - u32_darray_push(indices, top_right); - u32_darray_push(indices, bot_left); - } - } - - BufferHandle indices_handle = - GPU_BufferCreate(indices_count * sizeof(u32), BUFFER_INDEX, BUFFER_FLAG_GPU, indices->data); - storage->index_buffer = indices_handle; -} - -Heightmap Heightmap_FromImage(Str8 filepath) { - size_t max_size = MB(16); - arena arena = arena_create(malloc(max_size), max_size); - // str8_opt maybe_file = str8_from_file(&arena, filepath); - // assert(maybe_file.has_value); - - TextureData hmap_tex = TextureDataLoad(Str8_to_cstr(&arena, filepath), false); - - // arena_free_storage(&arena); - - return (Heightmap){ - .pixel_dimensions = hmap_tex.description.extents, - .filepath = filepath, - .image_data = hmap_tex.image_data, - .num_channels = hmap_tex.description.num_channels, - .is_uploaded = false, - }; -} - -void Terrain_Draw(Terrain_Storage* storage) { - GPU_CmdEncoder* enc = GPU_GetDefaultEncoder(); - GPU_EncodeBindPipeline(enc, storage->hmap_pipeline); - RenderScene* scene = Render_GetScene(); - - Mat4 view, proj; - u32x2 dimensions = GPU_Swapchain_GetDimensions(); - Camera_ViewProj(&scene->camera, (f32)dimensions.x, (f32)dimensions.y, &view, &proj); - Binding_Camera camera_data = { .view = view, - .projection = proj, - .viewPos = vec4(scene->camera.position.x, scene->camera.position.y, - scene->camera.position.z, 1.0) }; - GPU_EncodeBindShaderData(enc, 0, Binding_Camera_GetLayout(&camera_data)); - - TerrainUniforms uniforms = { .tex_slot_1 = storage->texture }; - ShaderDataLayout terrain_data = TerrainUniforms_GetLayout(&uniforms); - GPU_EncodeBindShaderData(enc, 1, terrain_data); - - GPU_EncodeSetVertexBuffer(enc, storage->vertex_buffer); - GPU_EncodeSetIndexBuffer(enc, storage->index_buffer); - - GPU_EncodeDrawIndexedTris(enc, storage->indices_count); - // glDrawArrays(GL_POINTS, 0, storage->num_vertices); -} - -f32 Heightmap_HeightXZ(const Heightmap* hmap, u32 x, u32 z) { - // its single channel so only one byte per pixel - size_t position = x * hmap->pixel_dimensions.x + z; - u8* bytes = hmap->image_data; - u8 channel = bytes[position]; - float value = (float)channel / 2.0; /// 255.0; - return value; -} - -ShaderDataLayout TerrainUniforms_GetLayout(void* data) { - TerrainUniforms* d = data; - bool has_data = data != NULL; - - ShaderBinding b1 = { - .label = "TextureSlot1", - .kind = BINDING_TEXTURE, - .vis = VISIBILITY_FRAGMENT, - }; - - if (has_data) { - b1.data.texture.handle = d->tex_slot_1; - } - return (ShaderDataLayout){ .bindings = { b1 }, .binding_count = 1 }; -} diff --git a/src/systems/terrain.h b/src/systems/terrain.h deleted file mode 100644 index 5a96132..0000000 --- a/src/systems/terrain.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @file terrain.h - * @brief - */ - -#pragma once - -/* -Future: - - Chunked terrain - - Dynamic LOD -*/ - -#include "defines.h" -#include "maths_types.h" -#include "ral_types.h" -#include "render.h" -#include "str.h" - -typedef struct Heightmap { - Str8 filepath; - u32x2 pixel_dimensions; - void* image_data; - u32 num_channels; - bool is_uploaded; -} Heightmap; - -typedef struct Terrain_Storage { - // arena terrain_allocator; - u32x2 grid_dimensions; - f32 grid_scale; - u32 num_vertices; - Heightmap heightmap; // NULL = no heightmap - GPU_Renderpass* hmap_renderpass; - GPU_Pipeline* hmap_pipeline; - TextureHandle texture; - - bool hmap_loaded; - BufferHandle vertex_buffer; - BufferHandle index_buffer; - u32 indices_count; -} Terrain_Storage; - -// --- Public API -PUB bool Terrain_Init(Terrain_Storage* storage); -PUB void Terrain_Shutdown(Terrain_Storage* storage); -PUB void Terrain_Draw( - Terrain_Storage* storage); // NOTE: For now it renders directly to main framebuffer - -/** @brief Sets the active heightmap to be rendered and collided against. */ -PUB void Terrain_LoadHeightmap(Terrain_Storage* storage, Heightmap hmap, f32 grid_scale, - bool free_on_upload); -PUB Heightmap Heightmap_FromImage(Str8 filepath); -PUB Heightmap Heightmap_FromPerlin(/* TODO: perlin noise generation parameters */); - -PUB bool Terrain_IsActive(); // checks whether we have a loaded heightmap and it's being rendered - -/** @brief Get the height (the Y component) for a vertex at a particular coordinate in the heightmap - */ -PUB f32 Heightmap_HeightXZ(const Heightmap* hmap, u32 x, u32 z); - -/** @brief Calculate the normal vector of a vertex at a particular coordinate in the heightmap */ -PUB Vec3 Heightmap_NormalXZ(const Heightmap* hmap, f32 x, f32 z); - -// /** @brief Generate the `geometry_data` for a heightmap ready to be uploaded to the GPU */ -// Geometry geo_heightmap(arena* a, Heightmap heightmap); - -typedef struct TerrainUniforms { - TextureHandle tex_slot_1; -} TerrainUniforms; - -ShaderDataLayout TerrainUniforms_GetLayout(void* data);
\ No newline at end of file diff --git a/src/systems/text.c b/src/systems/text.c deleted file mode 100644 index 2bb5399..0000000 --- a/src/systems/text.c +++ /dev/null @@ -1 +0,0 @@ -// TODO: Port from previous repo
\ No newline at end of file diff --git a/src/systems/text.h b/src/systems/text.h deleted file mode 100644 index 983ffd6..0000000 --- a/src/systems/text.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @brief - */ -#pragma once - -#include <stb_truetype.h> - -#include "darray.h" -#include "defines.h" -#include "ral.h" -#include "render_types.h" - -// struct core; - -// /** @brief internal font struct */ -// typedef struct font { -// const char *name; -// stbtt_fontinfo stbtt_font; -// stbtt_bakedchar c_data[96]; -// texture_handle bitmap_tex; -// } font; - -// typedef struct draw_text_packet { -// char *contents; -// f32 x; -// f32 y; -// } draw_text_packet; - -// KITC_DECL_TYPED_ARRAY(draw_text_packet) - -// typedef struct text_system_state { -// font default_font; -// shader_handle glyph_shader; -// u32 glyph_vbo; -// u32 glyph_vao; -// draw_text_packet_darray *draw_cmd_buf; -// // TODO: fonts array or hashtable -// } text_system_state; - -// void text_system_render(text_system_state *text); - -// // --- Lifecycle functions -// bool text_system_init(text_system_state *text); -// void text_system_shutdown(text_system_state *text); - -// // --- Drawing - -// /** -// * @brief immediate mode draw text. -// * @note immediately emits draw calls causing a shader program switch if you weren't previously -// drawing text in the current frame. -// */ -// void draw_text(struct core *core, f32 x, f32 y, char *contents); diff --git a/src/transform_hierarchy.c b/src/transform_hierarchy.c deleted file mode 100644 index a5f4d97..0000000 --- a/src/transform_hierarchy.c +++ /dev/null @@ -1,185 +0,0 @@ - -/** - * @file transform_hierarchy.h - */ -#pragma once -#include "transform_hierarchy.h" -#include <stdlib.h> -#include <string.h> - -#include "core.h" -#include "log.h" -#include "maths.h" -#include "maths_types.h" -#include "render_types.h" - -// struct transform_hierarchy { -// transform_node root; -// }; - -// transform_hierarchy* transform_hierarchy_create() { -// transform_hierarchy* tfh = malloc(sizeof(struct transform_hierarchy)); - -// tfh->root = (transform_node){ .model = { ABSENT_MODEL_HANDLE }, -// .tf = TRANSFORM_DEFAULT, -// .local_matrix_tf = mat4_ident(), -// .world_matrix_tf = mat4_ident(), -// .parent = NULL, -// .children = { 0 }, -// .n_children = 0, -// .tfh = tfh }; -// return tfh; -// } - -// bool free_node(transform_node* node, void* _ctx_data) { -// if (!node) return true; // leaf node -// if (node == &node->tfh->root) { -// WARN("You can't free the root node!"); -// return false; -// } - -// printf("Freed node\n"); -// free(node); -// return true; -// } - -// void transform_hierarchy_free(transform_hierarchy* tfh) { -// transform_hierarchy_dfs(&tfh->root, free_node, false, NULL); -// free(tfh); -// } - -// transform_node* transform_hierarchy_root_node(transform_hierarchy* tfh) { return &tfh->root; } - -// transform_node* transform_hierarchy_add_node(transform_node* parent, ModelHandle model, -// Transform tf) { -// if (!parent) { -// WARN("You tried to add a node to a bad parent (NULL?)"); -// return NULL; -// } -// transform_node* node = malloc(sizeof(transform_node)); -// node->model = model; -// node->tf = tf; -// node->local_matrix_tf = mat4_ident(); -// node->world_matrix_tf = mat4_ident(); -// node->parent = parent; -// memset(node->children, 0, sizeof(node->children)); -// node->n_children = 0; -// node->tfh = parent->tfh; - -// // push into parent's children array -// u32 next_index = parent->n_children; -// if (next_index == MAX_TF_NODE_CHILDREN) { -// ERROR("This transform hierarchy node already has MAX children. Dropping."); -// free(node); -// } else { -// parent->children[next_index] = node; -// parent->n_children++; -// } - -// return node; -// } - -// void transform_hierarchy_delete_node(transform_node* node) { -// // delete all children -// for (u32 i = 0; i < node->n_children; i++) { -// transform_node* child = node->children[i]; -// transform_hierarchy_dfs(child, free_node, false, NULL); -// } - -// if (node->parent) { -// for (u32 i = 0; i < node->parent->n_children; i++) { -// transform_node* child = node->parent->children[i]; -// if (child == node) { -// node->parent->children[i] = NULL; // HACK: this will leave behind empty slots in the -// // children array of the parent. oh well. -// } -// } -// } - -// free(node); -// } - -// void transform_hierarchy_dfs(transform_node* start_node, -// bool (*visit_node)(transform_node* node, void* ctx_data), -// bool is_pre_order, void* ctx_data) { -// if (!start_node) return; - -// bool continue_traversal = true; -// if (is_pre_order) { -// continue_traversal = visit_node(start_node, ctx_data); -// } - -// if (continue_traversal) { -// for (u32 i = 0; i < start_node->n_children; i++) { -// transform_node* child = start_node->children[i]; -// transform_hierarchy_dfs(child, visit_node, is_pre_order, ctx_data); -// } -// } - -// if (!is_pre_order) { -// // post-order -// visit_node(start_node, ctx_data); -// } -// } - -// // Update matrix for the current node -// bool update_matrix(transform_node* node, void* _ctx_data) { -// if (!node) return true; // leaf node - -// if (node->parent && node->parent->tf.is_dirty) { -// node->tf.is_dirty = true; -// } - -// if (node->tf.is_dirty) { -// // invalidates children -// Mat4 updated_local_transform = transform_to_mat(&node->tf); -// node->local_matrix_tf = updated_local_transform; -// if (node->parent) { -// Mat4 updated_world_transform = -// mat4_mult(node->parent->world_matrix_tf, updated_local_transform); -// node->world_matrix_tf = updated_world_transform; -// } -// } - -// return true; -// } - -// void transform_hierarchy_propagate_transforms(transform_hierarchy* tfh) { -// // kickoff traversal -// transform_hierarchy_dfs(&tfh->root, update_matrix, false, NULL); -// } - -// struct print_ctx { -// Core* core; -// u32 indentation_lvl; -// }; - -// bool print_node(transform_node* node, void* ctx_data) { -// struct print_ctx* ctx = (struct print_ctx*)ctx_data; - -// if (!node) return true; -// if (!node->parent) { -// printf("Root Node\n"); -// ctx->indentation_lvl++; -// return true; -// } - -// // Grab the model -// // FIXME -// // model m = ctx->core->models->data[node->model.raw]; -// for (int i = 0; i < ctx->indentation_lvl; i++) { -// printf(" "); -// } -// // printf("Node %s\n", m.name.buf); -// ctx->indentation_lvl++; - -// return true; -// } - -// void transform_hierarchy_debug_print(transform_node* start_node, Core* core) { -// struct print_ctx* ctx = malloc(sizeof(struct print_ctx)); -// ctx->core = core; -// ctx->indentation_lvl = 0; -// transform_hierarchy_dfs(start_node, print_node, true, (void*)ctx); -// free(ctx); -// } diff --git a/src/transform_hierarchy.h b/src/transform_hierarchy.h deleted file mode 100644 index 142ea99..0000000 --- a/src/transform_hierarchy.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @file transform_hierarchy.h - */ -#pragma once - -#include "maths_types.h" -#include "ral.h" -#include "render_types.h" - -#define MAX_TF_NODE_CHILDREN \ - 32 /** TEMP: Make it simpler to manage children in `transform_node`s */ - -typedef struct TransformHierarchy TransformHierarchy; - -struct Transform_Node { - ModelHandle model; /** A handle back to what model this node represents */ - Transform tf; - Mat4 local_matrix_tf; /** cached local affine transform */ - Mat4 world_matrix_tf; /** cached world-space affine transform */ - - struct transform_node* parent; - struct transform_node* children[MAX_TF_NODE_CHILDREN]; - u32 n_children; - struct transform_hierarchy* tfh; -}; -typedef struct Transform_Node Transform_Node; -typedef struct Transform_Node TF_Node; - -// --- Lifecycle - -/** @brief Allocates and returns an empty transform hierarchy with a root node */ -TransformHierarchy* TransformHierarchy_Create(); - -// /** -// * @brief recursively frees all the children and then finally itself -// * @note in the future we can use an object pool for the nodes -// */ -// void transform_hierarchy_free(transform_hierarchy* tfh); - -// // --- Main usecase - -// /** @brief Updates matrices of any invalidated nodes based on the `is_dirty` flag inside -// `transform` -// */ -// void transform_hierarchy_propagate_transforms(transform_hierarchy* tfh); - -// // --- Queries - -// /** @brief Get a pointer to the root node */ -// Transform_Node* TransformHierarchy_RootNode(TransformHierarchy* tfh); - -// // --- Mutations -// Transform_Node* TransformHierarchy_AddNode(transform_node* parent, ModelHandle model, -// Transform tf); -// void transform_hierarchy_delete_node(transform_node* node); - -// // --- Traversal - -// /** -// * @brief Perform a depth-first search traversal starting from `start_node`. -// * @param start_node The starting node of the traversal. -// * @param visit_node The function to call for each node visited. The callback should return false -// to stop the traversal early. -// * @param is_pre_order Indicates whether to do pre-order or post-order traversal i.e. when to -// call the `visit_node` function. -// * @param ctx_data An optional pointer to data that is be passed on each call to `visit_node`. -// Can be used to carry additional information or context. -// * -// * @note The main use-cases are: -// 1. traversing the whole tree to update cached 4x4 affine transform matrices -// (post-order) -// 2. freeing child nodes after deleting a node in the tree (post-order) -// 3. debug pretty printing the whole tree (post-order) -// */ -// void transform_hierarchy_dfs(transform_node* start_node, -// bool (*visit_node)(transform_node* node, void* ctx_data), -// bool is_pre_order, void* ctx_data); - -// struct Core; -// void transform_hierarchy_debug_print(transform_node* start_node, struct Core* core); |