From 824579234685171f0ca78674c7c18dfe6b43fe6e Mon Sep 17 00:00:00 2001 From: omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Wed, 29 May 2024 14:10:55 +1000 Subject: start adding opengl backend --- examples/cube/ex_cube.c | 4 +- src/renderer/backends/backend_opengl.c | 171 ----------------- src/renderer/backends/backend_vulkan.c | 4 + src/renderer/backends/backend_vulkan.h | 3 + src/renderer/backends/opengl/backend_opengl.c | 265 ++++++++++++++++++++++++++ src/renderer/backends/opengl/backend_opengl.h | 28 +++ src/renderer/render_types.h | 4 + xmake.lua | 14 +- 8 files changed, 314 insertions(+), 179 deletions(-) delete mode 100644 src/renderer/backends/backend_opengl.c create mode 100644 src/renderer/backends/opengl/backend_opengl.c create mode 100644 src/renderer/backends/opengl/backend_opengl.h diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c index 68ce0d5..b87071f 100644 --- a/examples/cube/ex_cube.c +++ b/examples/cube/ex_cube.c @@ -125,8 +125,8 @@ int main() { .scale = 1.0 }; mat4 model = transform_to_mat(&transform); mat4 view, proj; - camera_view_projection(&cam, g_core.renderer.swapchain.extent.width, - g_core.renderer.swapchain.extent.height, &view, &proj); + camera_view_projection(&cam, g_core.renderer.swapchain.dimensions.x, + g_core.renderer.swapchain.dimensions.y, &view, &proj); mvp_uniforms mvp_data = { .model = model, .view = view, .projection = proj }; my_shader_bind_group shader_bind_data = { .mvp = mvp_data, .tex = texture }; mvp_uniforms_data.data = &shader_bind_data; diff --git a/src/renderer/backends/backend_opengl.c b/src/renderer/backends/backend_opengl.c deleted file mode 100644 index 4cd97b5..0000000 --- a/src/renderer/backends/backend_opengl.c +++ /dev/null @@ -1,171 +0,0 @@ -#include -#include "camera.h" -#define CEL_PLATFORM_LINUX - -#include "defines.h" -#include "file.h" -#include "log.h" -#include "maths_types.h" -#include "ral.h" - -#if CEL_REND_BACKEND_OPENGL - -#include - -#include - -/** @brief Internal backend state */ -typedef struct opengl_state { -} opengl_state; - -bool gfx_backend_init(renderer *ren) { - INFO("loading OpenGL backend"); - - // glfwInit(); // Already handled in `renderer_init` - 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); - - opengl_state *internal = malloc(sizeof(opengl_state)); - ren->backend_context = (void *)internal; - - return true; -} - -void gfx_backend_draw_frame(renderer *ren, camera *cam, mat4 model, texture *tex) {} - -void gfx_backend_shutdown(renderer *ren) {} - -void uniform_vec3f(u32 program_id, const char *uniform_name, vec3 *value) { - glUniform3fv(glGetUniformLocation(program_id, uniform_name), 1, &value->x); -} -void uniform_f32(u32 program_id, const char *uniform_name, f32 value) { - glUniform1f(glGetUniformLocation(program_id, uniform_name), value); -} -void uniform_i32(u32 program_id, const char *uniform_name, i32 value) { - glUniform1i(glGetUniformLocation(program_id, uniform_name), value); -} -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; - } -} - -void draw_primitives(cel_primitive_topology primitive, u32 start_index, u32 count) { - u32 gl_primitive = to_gl_prim_topology(primitive); - glDrawArrays(gl_primitive, start_index, count); -} - -shader 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); - - shader s = { .program_id = shader_prog }; - return s; -} - -void set_shader(shader s) { glUseProgram(s.program_id); } - -#endif \ No newline at end of file diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index 2f8fdf7..10358f1 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -1,3 +1,5 @@ +#if defined (CEL_REND_BACKEND_VULKAN) + #include #include #include @@ -1708,3 +1710,5 @@ void backend_pools_init(arena* a, gpu_backend_pools* backend_pools) { context.gpu_pools; } + +#endif \ No newline at end of file diff --git a/src/renderer/backends/backend_vulkan.h b/src/renderer/backends/backend_vulkan.h index dc0f7bd..d92aa77 100644 --- a/src/renderer/backends/backend_vulkan.h +++ b/src/renderer/backends/backend_vulkan.h @@ -1,4 +1,5 @@ #pragma once +#if defined (CEL_REND_BACKEND_VULKAN) #include #include #include @@ -35,6 +36,7 @@ typedef struct gpu_swapchain { VkSwapchainKHR handle; arena swapchain_arena; VkExtent2D extent; + u32x2 dimensions; VkSurfaceFormatKHR image_format; VkPresentModeKHR present_mode; u32 image_count; @@ -113,3 +115,4 @@ typedef struct gpu_texture { VkSampler sampler; char* debug_label; } gpu_texture; +#endif \ No newline at end of file diff --git a/src/renderer/backends/opengl/backend_opengl.c b/src/renderer/backends/opengl/backend_opengl.c new file mode 100644 index 0000000..4ceba8f --- /dev/null +++ b/src/renderer/backends/opengl/backend_opengl.c @@ -0,0 +1,265 @@ +#define CEL_REND_BACKEND_OPENGL +#if defined(CEL_REND_BACKEND_OPENGL) +#include +#include "camera.h" + +#include "defines.h" +#include "file.h" +#include "log.h" +#include "maths_types.h" +#include "ral.h" +#include "backend_opengl.h" + +#include +#include + +typedef struct opengl_context {} opengl_context; + +static opengl_context context; + +struct GLFWwindow; + +bool gpu_backend_init(const char* window_name, struct GLFWwindow* window) { + INFO("loading OpenGL backend"); + 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); + + return true; +} + +void gpu_backend_shutdown() {} +void resource_pools_init(arena* a, struct resource_pools* res_pools) {} + +bool gpu_device_create(gpu_device* out_device) {} +void gpu_device_destroy() {} + +// --- Render Pipeline +gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description) {} +void gpu_pipeline_destroy(gpu_pipeline* pipeline) {} + +// --- Renderpass +gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description) {} +void gpu_renderpass_destroy(gpu_renderpass* pass) {} + +// --- Swapchain +bool gpu_swapchain_create(gpu_swapchain* out_swapchain) {} +void gpu_swapchain_destroy(gpu_swapchain* swapchain) {} + +// --- Command buffer +gpu_cmd_encoder gpu_cmd_encoder_create(); +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) {} +void gpu_cmd_encoder_end_render(gpu_cmd_encoder* encoder) {} +void gpu_cmd_encoder_begin_compute() {} +gpu_cmd_encoder* gpu_get_default_cmd_encoder() {} + +/** @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) {} + +/** @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) {} +void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* data) {} +void encode_set_default_settings(gpu_cmd_encoder* encoder) {} +void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) {} +void encode_set_index_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) {} +void encode_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) {} + +// --- Buffers +buffer_handle gpu_buffer_create(u64 size, gpu_buffer_type buf_type, gpu_buffer_flags flags, + const void* data) {} +void gpu_buffer_destroy(buffer_handle buffer) {} +void gpu_buffer_upload(const void* data) {} + +// Textures +/** @brief Create a new GPU texture resource. + * @param create_view creates a texture view (with same dimensions) at the same time + * @param data if not NULL then the data stored at the pointer will be uploaded to the GPU texture + * @note automatically creates a sampler for you */ +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) {} + +// --- Vertex formats +bytebuffer vertices_as_bytebuffer(arena* a, vertex_format format, vertex_darray* vertices) {} + +// --- TEMP +bool gpu_backend_begin_frame() { return true; } +void gpu_backend_end_frame() {} +void gpu_temp_draw(size_t n_verts) {} + + +// /** @brief Internal backend state */ +// typedef struct opengl_state { +// } opengl_state; + +// bool gfx_backend_init(renderer *ren) { +// INFO("loading OpenGL backend"); + +// // glfwInit(); // Already handled in `renderer_init` +// 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); + +// opengl_state *internal = malloc(sizeof(opengl_state)); +// ren->backend_context = (void *)internal; + +// return true; +// } + +// void gfx_backend_draw_frame(renderer *ren, camera *cam, mat4 model, texture *tex) {} + +// void gfx_backend_shutdown(renderer *ren) {} + +// void uniform_vec3f(u32 program_id, const char *uniform_name, vec3 *value) { +// glUniform3fv(glGetUniformLocation(program_id, uniform_name), 1, &value->x); +// } +// void uniform_f32(u32 program_id, const char *uniform_name, f32 value) { +// glUniform1f(glGetUniformLocation(program_id, uniform_name), value); +// } +// void uniform_i32(u32 program_id, const char *uniform_name, i32 value) { +// glUniform1i(glGetUniformLocation(program_id, uniform_name), value); +// } +// 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; +// } +// } + +// void draw_primitives(cel_primitive_topology primitive, u32 start_index, u32 count) { +// u32 gl_primitive = to_gl_prim_topology(primitive); +// glDrawArrays(gl_primitive, start_index, count); +// } + +// shader 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); + +// shader s = { .program_id = shader_prog }; +// return s; +// } + +// void set_shader(shader s) { glUseProgram(s.program_id); } + +#endif \ No newline at end of file diff --git a/src/renderer/backends/opengl/backend_opengl.h b/src/renderer/backends/opengl/backend_opengl.h new file mode 100644 index 0000000..3bc742d --- /dev/null +++ b/src/renderer/backends/opengl/backend_opengl.h @@ -0,0 +1,28 @@ +#pragma once + +#define CEL_REND_BACKEND_OPENGL + +#if defined(CEL_REND_BACKEND_OPENGL) + +#include "defines.h" +#include "maths_types.h" + +typedef struct gpu_swapchain { + u32x2 dimensions; +} gpu_swapchain; +typedef struct gpu_device {} gpu_device; +typedef struct gpu_pipeline_layout {} gpu_pipeline_layout; +typedef struct gpu_pipeline {} gpu_pipeline; +typedef struct gpu_renderpass {} gpu_renderpass; +typedef struct gpu_cmd_encoder {} gpu_cmd_encoder; // Recording +typedef struct gpu_cmd_buffer {} gpu_cmd_buffer; // Ready for submission + +typedef struct gpu_buffer { + union { + u32 vbo; + u32 ibo; + } id; +} gpu_buffer; +typedef struct gpu_texture {} gpu_texture; + +#endif \ No newline at end of file diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index cc5fd93..ed5c6e1 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -15,7 +15,11 @@ #if defined(CEL_PLATFORM_WINDOWS) // #include "backend_dx11.h" #endif +#if defined (CEL_REND_BACKEND_VULKAN) #include "backend_vulkan.h" +#elif defined (CEL_REND_BACKEND_OPENGL) +#include "backend_opengl.h" +#endif struct GLFWwindow; diff --git a/xmake.lua b/xmake.lua index 40ef961..09082ff 100644 --- a/xmake.lua +++ b/xmake.lua @@ -62,6 +62,7 @@ local core_sources = { "src/physics/*.c", "src/renderer/*.c", "src/renderer/backends/*.c", + "src/renderer/backends/opengl/*.c", "src/resources/*.c", "src/std/*.c", "src/std/containers/*.c", @@ -113,17 +114,18 @@ target("core_config") add_includedirs("src/physics/", {public = true}) add_includedirs("src/renderer/", {public = true}) add_includedirs("src/renderer/backends/", {public = true}) + add_includedirs("src/renderer/backends/opengl", {public = true}) add_includedirs("src/resources/", {public = true}) add_includedirs("src/std/", {public = true}) add_includedirs("src/std/containers", {public = true}) add_includedirs("src/systems/", {public = true}) add_files("src/empty.c") -- for some reason we need this on Mac so it doesnt call 'ar' with no files and error - add_rules("compile_glsl_vert_shaders") - add_rules("compile_glsl_frag_shaders") - add_files("assets/shaders/triangle.vert") - add_files("assets/shaders/triangle.frag") - add_files("assets/shaders/cube.vert") - add_files("assets/shaders/cube.frag") + -- add_rules("compile_glsl_vert_shaders") + -- add_rules("compile_glsl_frag_shaders") + -- add_files("assets/shaders/triangle.vert") + -- add_files("assets/shaders/triangle.frag") + -- add_files("assets/shaders/cube.vert") + -- add_files("assets/shaders/cube.frag") -- add_files("assets/shaders/*.frag") if is_plat("windows") then add_includedirs("$(env VULKAN_SDK)/Include", {public = true}) -- cgit v1.2.3-70-g09d2 From baf787b9eb742b0c52ecf8c9ae319dbfb4ea0f1b Mon Sep 17 00:00:00 2001 From: Omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Wed, 29 May 2024 14:50:49 +1000 Subject: opengl clear color working --- examples/cube/ex_cube.c | 10 ++++++-- src/defines.h | 5 ++-- src/renderer/archive/old_backend_vulkan.c | 6 ++--- src/renderer/backends/backend_vulkan.c | 2 +- src/renderer/backends/opengl/backend_opengl.c | 37 ++++++++++++++++++++++----- src/renderer/backends/opengl/backend_opengl.h | 4 +-- src/renderer/render_types.h | 2 ++ xmake.lua | 7 +++-- 8 files changed, 51 insertions(+), 22 deletions(-) diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c index b87071f..7b0ab48 100644 --- a/examples/cube/ex_cube.c +++ b/examples/cube/ex_cube.c @@ -68,8 +68,14 @@ int main() { gpu_renderpass_desc pass_description = {}; gpu_renderpass* renderpass = gpu_renderpass_create(&pass_description); - str8 vert_path = str8lit("build/linux/x86_64/debug/cube.vert.spv"); - str8 frag_path = str8lit("build/linux/x86_64/debug/cube.frag.spv"); + str8 vert_path, frag_path; +#ifdef CEL_REND_BACKEND_OPENGL + vert_path = str8lit("assets/shaders/blinn_phong.vert"); + frag_path = str8lit("assets/shaders/blinn_phong.frag"); +#else + vert_path = str8lit("build/linux/x86_64/debug/cube.vert.spv"); + frag_path = str8lit("build/linux/x86_64/debug/cube.frag.spv"); +#endif 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) { diff --git a/src/defines.h b/src/defines.h index 4b6f8c7..a35dbf4 100644 --- a/src/defines.h +++ b/src/defines.h @@ -64,10 +64,11 @@ Renderer backend defines: #define CEL_REND_BACKEND_METAL 1 */ +// NOTE: The below is now handled in xmake.lua // Platform will inform renderer backend (unless user overrides) #if defined(CEL_PLATFORM_LINUX) -// #define CEL_REND_BACKEND_OPENGL 1 -#define CEL_REND_BACKEND_VULKAN 1 +#define CEL_REND_BACKEND_OPENGL 1 +// #define CEL_REND_BACKEND_VULKAN 1 #endif #if defined(CEL_PLATFORM_WINDOWS) diff --git a/src/renderer/archive/old_backend_vulkan.c b/src/renderer/archive/old_backend_vulkan.c index a18ca70..0dfba98 100644 --- a/src/renderer/archive/old_backend_vulkan.c +++ b/src/renderer/archive/old_backend_vulkan.c @@ -1,8 +1,8 @@ -#include "camera.h" -#include "primitives.h" #define CDEBUG -#define CEL_REND_BACKEND_VULKAN 1 +// #define CEL_REND_BACKEND_VULKAN 1 #if CEL_REND_BACKEND_VULKAN +#include "camera.h" +#include "primitives.h" // ^ Temporary #include diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index 10358f1..c3fad75 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -1,4 +1,4 @@ -#if defined (CEL_REND_BACKEND_VULKAN) +#if defined(CEL_REND_BACKEND_VULKAN) #include #include diff --git a/src/renderer/backends/opengl/backend_opengl.c b/src/renderer/backends/opengl/backend_opengl.c index 4ceba8f..cbc90f2 100644 --- a/src/renderer/backends/opengl/backend_opengl.c +++ b/src/renderer/backends/opengl/backend_opengl.c @@ -1,19 +1,22 @@ +#include "colours.h" #define CEL_REND_BACKEND_OPENGL #if defined(CEL_REND_BACKEND_OPENGL) #include #include "camera.h" +#include "backend_opengl.h" #include "defines.h" #include "file.h" #include "log.h" #include "maths_types.h" #include "ral.h" -#include "backend_opengl.h" #include #include -typedef struct opengl_context {} opengl_context; +typedef struct opengl_context { + GLFWwindow* window; +} opengl_context; static opengl_context context; @@ -21,11 +24,23 @@ struct GLFWwindow; bool gpu_backend_init(const char* window_name, struct GLFWwindow* window) { INFO("loading OpenGL backend"); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + + memset(&context, 0, sizeof(opengl_context)); + context.window = window; + + 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); + return true; } @@ -48,10 +63,17 @@ bool gpu_swapchain_create(gpu_swapchain* out_swapchain) {} void gpu_swapchain_destroy(gpu_swapchain* swapchain) {} // --- Command buffer -gpu_cmd_encoder gpu_cmd_encoder_create(); +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) {} +void gpu_cmd_encoder_begin_render(gpu_cmd_encoder* encoder, gpu_renderpass* renderpass) { + rgba clear_colour = STONE_900; + glClearColor(clear_colour.r, clear_colour.g, clear_colour.b, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} void gpu_cmd_encoder_end_render(gpu_cmd_encoder* encoder) {} void gpu_cmd_encoder_begin_compute() {} gpu_cmd_encoder* gpu_get_default_cmd_encoder() {} @@ -104,10 +126,11 @@ bytebuffer vertices_as_bytebuffer(arena* a, vertex_format format, vertex_darray* // --- TEMP bool gpu_backend_begin_frame() { return true; } -void gpu_backend_end_frame() {} +void gpu_backend_end_frame() { + glfwSwapBuffers(context.window); +} void gpu_temp_draw(size_t n_verts) {} - // /** @brief Internal backend state */ // typedef struct opengl_state { // } opengl_state; diff --git a/src/renderer/backends/opengl/backend_opengl.h b/src/renderer/backends/opengl/backend_opengl.h index 3bc742d..649bc7b 100644 --- a/src/renderer/backends/opengl/backend_opengl.h +++ b/src/renderer/backends/opengl/backend_opengl.h @@ -1,8 +1,6 @@ #pragma once -#define CEL_REND_BACKEND_OPENGL - -#if defined(CEL_REND_BACKEND_OPENGL) +#ifdef CEL_REND_BACKEND_OPENGL #include "defines.h" #include "maths_types.h" diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index ed5c6e1..aeedf85 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -21,6 +21,8 @@ #include "backend_opengl.h" #endif +#include "backend_opengl.h" + struct GLFWwindow; /** @brief configuration passed to the renderer at init time */ diff --git a/xmake.lua b/xmake.lua index 09082ff..5a2707c 100644 --- a/xmake.lua +++ b/xmake.lua @@ -17,11 +17,10 @@ elseif is_mode("release") then add_defines("CRELEASE") end - -- Platform defines and system packages if is_plat("linux") then add_defines("CEL_PLATFORM_LINUX") - add_syslinks("vulkan", "dl", "X11", "pthread") + add_syslinks("dl", "X11", "pthread") elseif is_plat("windows") then add_defines("CEL_PLATFORM_WINDOWS") add_syslinks("user32", "gdi32", "kernel32", "shell32") @@ -95,12 +94,11 @@ rule("compile_glsl_frag_shaders") end) -- TODO: Metal shaders compilation --- - -- common configuration for both static and shared libraries target("core_config") set_kind("static") -- kind is required but you can ignore it since it's just for common settings add_packages("local_glfw") + add_defines("CEL_REND_BACKEND_OPENGL") add_includedirs("deps/cgltf", {public = true}) add_includedirs("deps/glfw-3.3.8/include/GLFW", {public = true}) add_includedirs("deps/glad/include", {public = true}) @@ -172,6 +170,7 @@ target("tri") target("cube") set_kind("binary") set_group("examples") + -- add_defines("CEL_REND_BACKEND_OPENGL") add_deps("core_static") add_files("examples/cube/ex_cube.c") set_rundir("$(projectdir)") -- cgit v1.2.3-70-g09d2 From 59854f60b761d77cee4095c9ce45062c926dea5a Mon Sep 17 00:00:00 2001 From: Omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Thu, 30 May 2024 22:19:07 +1000 Subject: wip --- assets/shaders/blinn_phong.frag | 2 +- assets/shaders/blinn_phong.vert | 27 +++-- assets/shaders/cube.vert | 3 +- src/renderer/archive/render_backend.h | 2 +- src/renderer/archive/render_types.h | 8 +- src/renderer/backends/backend_vulkan.c | 12 +-- src/renderer/backends/opengl/backend_opengl.c | 142 +++++++++++++++++++++++--- src/renderer/backends/opengl/backend_opengl.h | 11 +- src/renderer/ral.c | 23 +++++ src/renderer/ral.h | 2 + 10 files changed, 187 insertions(+), 45 deletions(-) diff --git a/assets/shaders/blinn_phong.frag b/assets/shaders/blinn_phong.frag index a0ba905..f7c4322 100644 --- a/assets/shaders/blinn_phong.frag +++ b/assets/shaders/blinn_phong.frag @@ -32,7 +32,7 @@ in VS_OUT { vec3 FragPos; vec3 Normal; vec2 TexCoords; - vec4 FragPosLightSpace; + // vec4 FragPosLightSpace; vec4 Color; } fs_in; diff --git a/assets/shaders/blinn_phong.vert b/assets/shaders/blinn_phong.vert index 06dc5e7..aefb129 100644 --- a/assets/shaders/blinn_phong.vert +++ b/assets/shaders/blinn_phong.vert @@ -1,28 +1,37 @@ -#version 410 core +#version 450 core + +struct Uniforms { + mat4 model; + mat4 view; + mat4 projection; +}; + +uniform Uniforms ubo; + // Inputs layout (location = 0) in vec3 inPos; layout (location = 1) in vec3 inNormal; layout (location = 2) in vec2 inTexCoords; -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; -uniform mat4 lightSpaceMatrix; +// uniform mat4 model; +// uniform mat4 view; +// uniform mat4 projection; +// uniform mat4 lightSpaceMatrix; // Output out VS_OUT { vec3 FragPos; vec3 Normal; vec2 TexCoords; - vec4 FragPosLightSpace; + // vec4 FragPosLightSpace; vec4 Color; } vs_out; void main() { - vs_out.FragPos = vec3(model * vec4(inPos, 1.0)); + vs_out.FragPos = vec3(ubo.model * vec4(inPos, 1.0)); vs_out.Normal = inNormal; vs_out.TexCoords = inTexCoords; - vs_out.FragPosLightSpace = lightSpaceMatrix * vec4(vs_out.FragPos, 1.0); + // vs_out.FragPosLightSpace = lightSpaceMatrix * vec4(vs_out.FragPos, 1.0); vs_out.Color = vec4(1.0); - gl_Position = projection * view * model * vec4(inPos, 1.0); + gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos, 1.0); } \ No newline at end of file diff --git a/assets/shaders/cube.vert b/assets/shaders/cube.vert index dc625ec..fa9f85b 100644 --- a/assets/shaders/cube.vert +++ b/assets/shaders/cube.vert @@ -4,8 +4,7 @@ layout(binding = 0) uniform UniformBufferObject { mat4 model; mat4 view; mat4 proj; -} -ubo; +} ubo; layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inNormal; diff --git a/src/renderer/archive/render_backend.h b/src/renderer/archive/render_backend.h index da30bcc..6df9c81 100644 --- a/src/renderer/archive/render_backend.h +++ b/src/renderer/archive/render_backend.h @@ -22,7 +22,7 @@ void clear_screen(vec3 colour); void texture_data_upload(texture* tex); void bind_texture(shader s, texture* tex, u32 slot); void bind_mesh_vertex_buffer(void* backend, mesh* mesh); -void draw_primitives(cel_primitive_topology primitive, u32 start_index, u32 count); +// void draw_primitives(cel_primitive_topology primitive, u32 start_index, u32 count); shader shader_create_separate(const char* vert_shader, const char* frag_shader); void set_shader(shader s); diff --git a/src/renderer/archive/render_types.h b/src/renderer/archive/render_types.h index f5ea986..5ee3316 100644 --- a/src/renderer/archive/render_types.h +++ b/src/renderer/archive/render_types.h @@ -147,10 +147,10 @@ typedef struct mesh { u32 vbo, vao; /** OpenGL data. TODO: dont leak OpenGL details */ } mesh; -// #ifndef TYPED_MESH_ARRAY -// KITC_DECL_TYPED_ARRAY(mesh) // creates "mesh_darray" -// #define TYPED_MESH_ARRAY -// #endif +#ifndef TYPED_MESH_ARRAY +KITC_DECL_TYPED_ARRAY(mesh) // creates "mesh_darray" +#define TYPED_MESH_ARRAY +#endif typedef struct model { str8 name; diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index c3fad75..25a78e7 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -1699,16 +1699,6 @@ void resource_pools_init(arena* a, struct resource_pools* res_pools) { context.resource_pools = res_pools; } -void backend_pools_init(arena* a, gpu_backend_pools* backend_pools) { - pipeline_layout_pool pipeline_layout_pool = - pipeline_layout_pool_create(a, MAX_PIPELINES, sizeof(gpu_pipeline_layout)); - 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; - - context.gpu_pools; -} + #endif \ No newline at end of file diff --git a/src/renderer/backends/opengl/backend_opengl.c b/src/renderer/backends/opengl/backend_opengl.c index cbc90f2..a933462 100644 --- a/src/renderer/backends/opengl/backend_opengl.c +++ b/src/renderer/backends/opengl/backend_opengl.c @@ -1,4 +1,5 @@ #include "colours.h" +#include "ral_types.h" #define CEL_REND_BACKEND_OPENGL #if defined(CEL_REND_BACKEND_OPENGL) #include @@ -16,6 +17,8 @@ typedef struct opengl_context { GLFWwindow* window; + arena pool_arena; + gpu_backend_pools gpu_pools; } opengl_context; static opengl_context context; @@ -28,6 +31,11 @@ bool gpu_backend_init(const char* window_name, struct GLFWwindow* window) { 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); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); @@ -51,7 +59,25 @@ bool gpu_device_create(gpu_device* out_device) {} void gpu_device_destroy() {} // --- Render Pipeline -gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description) {} +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; + + // Allocate uniform buffers if needed + 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++) { + } + } + + return pipeline; +} void gpu_pipeline_destroy(gpu_pipeline* pipeline) {} // --- Renderpass @@ -97,8 +123,19 @@ void copy_buffer_to_buffer_oneshot(buffer_handle src, u64 src_offset, buffer_han 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) {} -void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* data) {} +void encode_bind_pipeline(gpu_cmd_encoder* encoder, pipeline_kind kind, gpu_pipeline* pipeline) { + // In OpenGL this 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); + size_t binding_count = sdl.bindings_count; + + for (u32 i = 0; i < sdl.bindings_count; i++) { + shader_binding binding = sdl.bindings[i]; + + } +} void encode_set_default_settings(gpu_cmd_encoder* encoder) {} void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) {} void encode_set_index_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) {} @@ -108,7 +145,28 @@ 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) {} + const void* data) { + GLuint gl_buffer_id; + glGenBuffers(1, &gl_buffer_id); + + switch (buf_type) { + case CEL_BUFFER_UNIFORM: + glBindBuffer(GL_UNIFORM_BUFFER, gl_buffer_id); + case CEL_BUFFER_DEFAULT: + case CEL_BUFFER_VERTEX: + case CEL_BUFFER_INDEX: + WARN("Unimplemented gpu_buffer_type!"); + break; + case CEL_BUFFER_COUNT: + WARN("Incorrect gpu_buffer_type provided."); + break; + } + + buffer_handle handle; + gpu_buffer* buffer = buffer_pool_alloc(&context.resource_pools, &handle); + +} + void gpu_buffer_destroy(buffer_handle buffer) {} void gpu_buffer_upload(const void* data) {} @@ -131,6 +189,58 @@ void gpu_backend_end_frame() { } 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; +} + // /** @brief Internal backend state */ // typedef struct opengl_state { // } opengl_state; @@ -163,18 +273,18 @@ void gpu_temp_draw(size_t n_verts) {} // void gfx_backend_shutdown(renderer *ren) {} -// void uniform_vec3f(u32 program_id, const char *uniform_name, vec3 *value) { -// glUniform3fv(glGetUniformLocation(program_id, uniform_name), 1, &value->x); -// } -// void uniform_f32(u32 program_id, const char *uniform_name, f32 value) { -// glUniform1f(glGetUniformLocation(program_id, uniform_name), value); -// } -// void uniform_i32(u32 program_id, const char *uniform_name, i32 value) { -// glUniform1i(glGetUniformLocation(program_id, uniform_name), value); -// } -// void uniform_mat4f(u32 program_id, const char *uniform_name, mat4 *value) { -// glUniformMatrix4fv(glGetUniformLocation(program_id, uniform_name), 1, GL_FALSE, value->data); -// } +void uniform_vec3f(u32 program_id, const char *uniform_name, vec3 *value) { + glUniform3fv(glGetUniformLocation(program_id, uniform_name), 1, &value->x); +} +void uniform_f32(u32 program_id, const char *uniform_name, f32 value) { + glUniform1f(glGetUniformLocation(program_id, uniform_name), value); +} +void uniform_i32(u32 program_id, const char *uniform_name, i32 value) { + glUniform1i(glGetUniformLocation(program_id, uniform_name), value); +} +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); diff --git a/src/renderer/backends/opengl/backend_opengl.h b/src/renderer/backends/opengl/backend_opengl.h index 649bc7b..784c061 100644 --- a/src/renderer/backends/opengl/backend_opengl.h +++ b/src/renderer/backends/opengl/backend_opengl.h @@ -10,7 +10,9 @@ typedef struct gpu_swapchain { } gpu_swapchain; typedef struct gpu_device {} gpu_device; typedef struct gpu_pipeline_layout {} gpu_pipeline_layout; -typedef struct gpu_pipeline {} gpu_pipeline; +typedef struct gpu_pipeline { + u32 shader_id; +} gpu_pipeline; typedef struct gpu_renderpass {} gpu_renderpass; typedef struct gpu_cmd_encoder {} gpu_cmd_encoder; // Recording typedef struct gpu_cmd_buffer {} gpu_cmd_buffer; // Ready for submission @@ -23,4 +25,11 @@ typedef struct gpu_buffer { } gpu_buffer; typedef struct gpu_texture {} gpu_texture; + +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 \ No newline at end of file diff --git a/src/renderer/ral.c b/src/renderer/ral.c index 7d868be..4f2a999 100644 --- a/src/renderer/ral.c +++ b/src/renderer/ral.c @@ -1,5 +1,7 @@ #include "ral.h" +#include "backend_opengl.h" + size_t vertex_attrib_size(vertex_attrib_type attr) { switch (attr) { case ATTR_F32: @@ -40,3 +42,24 @@ vertex_description static_3d_vertex_description() { vertex_desc_add(&builder, "texCoords", ATTR_F32x2); return builder; } + +void backend_pools_init(arena* a, gpu_backend_pools* backend_pools) { + pipeline_layout_pool pipeline_layout_pool = + pipeline_layout_pool_create(a, MAX_PIPELINES, sizeof(gpu_pipeline_layout)); + 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; + + // context.gpu_pools; +} + +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; +} \ No newline at end of file diff --git a/src/renderer/ral.h b/src/renderer/ral.h index 1ca37b4..a18ea87 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -50,11 +50,13 @@ typedef struct gpu_backend_pools { pipeline_layout_pool pipeline_layouts; renderpass_pool renderpasses; } gpu_backend_pools; +void backend_pools_init(arena* a, gpu_backend_pools* backend_pools); struct resource_pools { buffer_pool buffers; texture_pool textures; }; +void resource_pools_init(arena* a, struct resource_pools* res_pools); // --- Pipeline description typedef enum pipeline_kind { -- cgit v1.2.3-70-g09d2 From 34cfaac69eda7eae258d004e4cafd5a816cf9b67 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Fri, 7 Jun 2024 12:09:25 +1000 Subject: drop glsl version --- assets/shaders/blinn_phong.frag | 4 ++-- assets/shaders/blinn_phong.vert | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/shaders/blinn_phong.frag b/assets/shaders/blinn_phong.frag index f7c4322..267c71b 100644 --- a/assets/shaders/blinn_phong.frag +++ b/assets/shaders/blinn_phong.frag @@ -1,4 +1,4 @@ -#version 410 core +#version 430 core out vec4 FragColor; // A Blinn-Phong material with textures for diffuse and specular @@ -94,4 +94,4 @@ vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir) diffuse *= attentuation; specular *= attentuation; return (ambient + diffuse + specular); -} \ No newline at end of file +} diff --git a/assets/shaders/blinn_phong.vert b/assets/shaders/blinn_phong.vert index aefb129..1d2a53e 100644 --- a/assets/shaders/blinn_phong.vert +++ b/assets/shaders/blinn_phong.vert @@ -1,4 +1,4 @@ -#version 450 core +#version 430 core struct Uniforms { mat4 model; @@ -34,4 +34,4 @@ void main() { // vs_out.FragPosLightSpace = lightSpaceMatrix * vec4(vs_out.FragPos, 1.0); vs_out.Color = vec4(1.0); gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos, 1.0); -} \ No newline at end of file +} -- cgit v1.2.3-70-g09d2 From f553d66891e6f77b0fa78c279f51a44d1c51ff9f Mon Sep 17 00:00:00 2001 From: Omniscient Date: Fri, 7 Jun 2024 12:10:32 +1000 Subject: add assert back that pool entry is at least as big as a pointer. add debug name for pools --- src/std/mem.c | 9 ++++++--- src/std/mem.h | 5 +++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/std/mem.c b/src/std/mem.c index a5321fb..a5a0b88 100644 --- a/src/std/mem.c +++ b/src/std/mem.c @@ -46,15 +46,18 @@ void arena_rewind(arena_save savepoint) { savepoint.arena->curr = savepoint.save // --- Pool -void_pool void_pool_create(arena* a, u64 capacity, u64 entry_size) { +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 }; + .free_list_head = NULL, + .debug_label = debug_label }; void_pool_free_all(&pool); @@ -99,7 +102,7 @@ void* void_pool_alloc(void_pool* pool, u32* out_raw_handle) { uintptr_t start = (uintptr_t)pool->backing_buffer; uintptr_t cur = (uintptr_t)free_node; TRACE("%ld %ld ", start, cur); - /* assert(cur > start); */ + assert(cur > start); u32 index = (u32)((cur - start) / pool->entry_size); printf("Index %d\n", index); if (out_raw_handle != NULL) { diff --git a/src/std/mem.h b/src/std/mem.h index 1d508ce..b256e27 100644 --- a/src/std/mem.h +++ b/src/std/mem.h @@ -48,9 +48,10 @@ typedef struct void_pool { u64 count; void* backing_buffer; void_pool_header* free_list_head; + const char* debug_label; } void_pool; -void_pool void_pool_create(arena* a, u64 capacity, u64 entry_size); +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); @@ -68,7 +69,7 @@ void void_pool_dealloc(void_pool* pool, u32 raw_handle); } Name##_pool; \ \ static Name##_pool Name##_pool_create(arena* a, u64 cap, u64 entry_size) { \ - void_pool p = void_pool_create(a, cap, entry_size); \ + 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) { \ -- cgit v1.2.3-70-g09d2 From 4976c723a7add3a1409eb529d088868a2c568fbb Mon Sep 17 00:00:00 2001 From: Omniscient Date: Fri, 7 Jun 2024 12:10:53 +1000 Subject: add vertex/index buffer binding in opengl --- src/renderer/backends/backend_vulkan.c | 16 +++++++-------- src/renderer/backends/opengl/backend_opengl.c | 29 ++++++++++++++++++--------- src/renderer/backends/opengl/backend_opengl.h | 14 +++++++------ src/renderer/ral_types.h | 8 ++++++++ src/resources/gltf.c | 5 +++-- src/resources/obj.c | 4 +++- 6 files changed, 49 insertions(+), 27 deletions(-) diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index 25a78e7..4ef1e31 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -1690,15 +1690,15 @@ void vulkan_transition_image_layout(gpu_texture* texture, VkFormat format, VkIma /* 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; +/* 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; -} +/* context.resource_pools = res_pools; */ +/* } */ -#endif \ No newline at end of file +#endif diff --git a/src/renderer/backends/opengl/backend_opengl.c b/src/renderer/backends/opengl/backend_opengl.c index a933462..cb25b46 100644 --- a/src/renderer/backends/opengl/backend_opengl.c +++ b/src/renderer/backends/opengl/backend_opengl.c @@ -18,7 +18,9 @@ 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; @@ -35,13 +37,15 @@ bool gpu_backend_init(const char* window_name, struct GLFWwindow* window) { 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_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); - // glad: load all OpenGL function pointers + // glad: load all opengl function pointers if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { ERROR("Failed to initialise GLAD \n"); return false; @@ -53,7 +57,6 @@ bool gpu_backend_init(const char* window_name, struct GLFWwindow* window) { } void gpu_backend_shutdown() {} -void resource_pools_init(arena* a, struct resource_pools* res_pools) {} bool gpu_device_create(gpu_device* out_device) {} void gpu_device_destroy() {} @@ -102,7 +105,9 @@ void gpu_cmd_encoder_begin_render(gpu_cmd_encoder* encoder, gpu_renderpass* rend } void gpu_cmd_encoder_end_render(gpu_cmd_encoder* encoder) {} void gpu_cmd_encoder_begin_compute() {} -gpu_cmd_encoder* gpu_get_default_cmd_encoder() {} +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) {} @@ -152,19 +157,23 @@ buffer_handle gpu_buffer_create(u64 size, gpu_buffer_type buf_type, gpu_buffer_f switch (buf_type) { case CEL_BUFFER_UNIFORM: glBindBuffer(GL_UNIFORM_BUFFER, gl_buffer_id); + break; case CEL_BUFFER_DEFAULT: case CEL_BUFFER_VERTEX: + glBindBuffer(GL_ARRAY_BUFFER, gl_buffer_id); + break; case CEL_BUFFER_INDEX: - WARN("Unimplemented gpu_buffer_type!"); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl_buffer_id); break; - case CEL_BUFFER_COUNT: - WARN("Incorrect gpu_buffer_type provided."); + default: + WARN("Unimplemented gpu_buffer_type provided %s", buffer_type_names[buf_type]); break; } buffer_handle handle; - gpu_buffer* buffer = buffer_pool_alloc(&context.resource_pools, &handle); - + gpu_buffer* buffer = buffer_pool_alloc(&context.resource_pools->buffers, &handle); + + return handle; } void gpu_buffer_destroy(buffer_handle buffer) {} @@ -395,4 +404,4 @@ void uniform_mat4f(u32 program_id, const char *uniform_name, mat4 *value) { // void set_shader(shader s) { glUseProgram(s.program_id); } -#endif \ No newline at end of file +#endif diff --git a/src/renderer/backends/opengl/backend_opengl.h b/src/renderer/backends/opengl/backend_opengl.h index 784c061..0ce765a 100644 --- a/src/renderer/backends/opengl/backend_opengl.h +++ b/src/renderer/backends/opengl/backend_opengl.h @@ -9,21 +9,23 @@ typedef struct gpu_swapchain { u32x2 dimensions; } gpu_swapchain; typedef struct gpu_device {} gpu_device; -typedef struct gpu_pipeline_layout {} gpu_pipeline_layout; +typedef struct gpu_pipeline_layout { void* pad } gpu_pipeline_layout; typedef struct gpu_pipeline { u32 shader_id; + u32 pad; } gpu_pipeline; -typedef struct gpu_renderpass {} gpu_renderpass; -typedef struct gpu_cmd_encoder {} gpu_cmd_encoder; // Recording -typedef struct gpu_cmd_buffer {} gpu_cmd_buffer; // Ready for submission +typedef struct gpu_renderpass { void* pad } gpu_renderpass; +typedef struct gpu_cmd_encoder { void* pad } 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; } id; + u32 pad; } gpu_buffer; -typedef struct gpu_texture {} gpu_texture; +typedef struct gpu_texture { void* pad } gpu_texture; u32 shader_create_separate(const char *vert_shader, const char *frag_shader); @@ -32,4 +34,4 @@ void uniform_vec3f(u32 program_id, const char *uniform_name, vec3 *value); void uniform_f32(u32 program_id, const char *uniform_name, f32 value); void uniform_i32(u32 program_id, const char *uniform_name, i32 value); void uniform_mat4f(u32 program_id, const char *uniform_name, mat4 *value); -#endif \ No newline at end of file +#endif diff --git a/src/renderer/ral_types.h b/src/renderer/ral_types.h index 704f2cb..5cbf6fd 100644 --- a/src/renderer/ral_types.h +++ b/src/renderer/ral_types.h @@ -77,6 +77,14 @@ typedef enum gpu_buffer_type { CEL_BUFFER_COUNT } gpu_buffer_type; +static const char* buffer_type_names[] = { + "RAL Buffer Default", + "RAL Buffer Vertex", + "RAL Buffer Index", + "RAL Buffer Uniform", + "RAL Buffer Count", +}; + typedef enum gpu_buffer_flag { CEL_BUFFER_FLAG_CPU = 1 << 0, CEL_BUFFER_FLAG_GPU = 1 << 1, diff --git a/src/resources/gltf.c b/src/resources/gltf.c index 022bf95..61b99d7 100644 --- a/src/resources/gltf.c +++ b/src/resources/gltf.c @@ -47,7 +47,8 @@ model_handle model_load_gltf(struct core *core, const char *path, bool invert_te model model = { 0 }; model.name = str8_cstr_view(path); - model.meshes = mesh_darray_new(1); + // FIXME: Use mesh* malloc'd + /* model.meshes = mesh_darray_new(1); */ // model.materials = material_darray_new(1); bool success = @@ -771,4 +772,4 @@ bool model_load_gltf(const char *path, model *out_model) { TRACE("Finished loading GLTF"); return true; } -*/ \ No newline at end of file +*/ diff --git a/src/resources/obj.c b/src/resources/obj.c index 888e16e..19d8657 100644 --- a/src/resources/obj.c +++ b/src/resources/obj.c @@ -54,7 +54,7 @@ model_handle model_load_obj(core *core, const char *path, bool invert_textures_y model model = { 0 }; model.name = str8_cstr_view(path); - model.meshes = mesh_darray_new(1); + /* model.meshes = mallocmesh_darray_new(1); */ // model.materials = material_darray_new(1); bool success = model_load_obj_str(file_string, relative_path.path, &model, invert_textures_y); @@ -228,6 +228,8 @@ bool model_load_obj_str(const char *file_string, str8 relative_path, model *out_ // // 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; } -- cgit v1.2.3-70-g09d2 From 44188d921c13111b61904f98ad06f8249e41d050 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Fri, 7 Jun 2024 12:12:53 +1000 Subject: fix pool test --- tests/pool_tests.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pool_tests.c b/tests/pool_tests.c index df65773..10a4bed 100644 --- a/tests/pool_tests.c +++ b/tests/pool_tests.c @@ -20,7 +20,7 @@ TEST(Pool, SanityCheckTest) { TEST_ASSERT_EQUAL(true, true); } TEST(Pool, Initialisation) { // u32 pool - void_pool pool = void_pool_create(&a, 256, sizeof(u32)); + void_pool pool = void_pool_create(&a, "Test pool", 256, sizeof(u32)); u32 x_handle; u32* x_ptr = (u32*)void_pool_alloc(&pool, &x_handle); // store something in it -- cgit v1.2.3-70-g09d2 From 5751ffae2eb8f786edb2dcd9e7f635fd1d0c1331 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Fri, 7 Jun 2024 12:13:22 +1000 Subject: chore: fmt --- src/renderer/backends/backend_vulkan.c | 2 -- src/renderer/backends/backend_vulkan.h | 2 +- src/renderer/backends/opengl/backend_opengl.c | 27 +++++++++++---------------- src/renderer/backends/opengl/backend_opengl.h | 24 +++++++++++++++++------- src/renderer/ral_types.h | 7 ++----- src/renderer/render_types.h | 4 ++-- src/std/mem.c | 2 +- src/std/mem.h | 2 +- 8 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index 4ef1e31..06d8898 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -1699,6 +1699,4 @@ void vulkan_transition_image_layout(gpu_texture* texture, VkFormat format, VkIma /* context.resource_pools = res_pools; */ /* } */ - - #endif diff --git a/src/renderer/backends/backend_vulkan.h b/src/renderer/backends/backend_vulkan.h index d92aa77..21a80ba 100644 --- a/src/renderer/backends/backend_vulkan.h +++ b/src/renderer/backends/backend_vulkan.h @@ -1,5 +1,5 @@ #pragma once -#if defined (CEL_REND_BACKEND_VULKAN) +#if defined(CEL_REND_BACKEND_VULKAN) #include #include #include diff --git a/src/renderer/backends/opengl/backend_opengl.c b/src/renderer/backends/opengl/backend_opengl.c index cb25b46..0cd2925 100644 --- a/src/renderer/backends/opengl/backend_opengl.c +++ b/src/renderer/backends/opengl/backend_opengl.c @@ -105,9 +105,7 @@ void gpu_cmd_encoder_begin_render(gpu_cmd_encoder* encoder, gpu_renderpass* rend } 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.command_buffer; -} +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) {} @@ -138,7 +136,6 @@ void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* d for (u32 i = 0; i < sdl.bindings_count; i++) { shader_binding binding = sdl.bindings[i]; - } } void encode_set_default_settings(gpu_cmd_encoder* encoder) {} @@ -193,18 +190,16 @@ bytebuffer vertices_as_bytebuffer(arena* a, vertex_format format, vertex_darray* // --- TEMP bool gpu_backend_begin_frame() { return true; } -void gpu_backend_end_frame() { - glfwSwapBuffers(context.window); -} +void gpu_backend_end_frame() { glfwSwapBuffers(context.window); } void gpu_temp_draw(size_t n_verts) {} -u32 shader_create_separate(const char *vert_shader, const char *frag_shader){ +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); + const char* vertex_shader_src = string_from_file(vert_shader); if (vertex_shader_src == NULL) { ERROR("EXIT: couldnt load shader"); exit(-1); @@ -221,7 +216,7 @@ u32 shader_create_separate(const char *vert_shader, const char *frag_shader){ // fragment shader u32 fragment = glCreateShader(GL_FRAGMENT_SHADER); - const char *fragment_shader_src = string_from_file(frag_shader); + const char* fragment_shader_src = string_from_file(frag_shader); if (fragment_shader_src == NULL) { ERROR("EXIT: couldnt load shader"); exit(-1); @@ -244,8 +239,8 @@ u32 shader_create_separate(const char *vert_shader, const char *frag_shader){ glLinkProgram(shader_prog); glDeleteShader(vertex); glDeleteShader(fragment); - free((char *)vertex_shader_src); - free((char *)fragment_shader_src); + free((char*)vertex_shader_src); + free((char*)fragment_shader_src); return shader_prog; } @@ -282,16 +277,16 @@ u32 shader_create_separate(const char *vert_shader, const char *frag_shader){ // void gfx_backend_shutdown(renderer *ren) {} -void uniform_vec3f(u32 program_id, const char *uniform_name, vec3 *value) { +void uniform_vec3f(u32 program_id, const char* uniform_name, vec3* value) { glUniform3fv(glGetUniformLocation(program_id, uniform_name), 1, &value->x); } -void uniform_f32(u32 program_id, const char *uniform_name, f32 value) { +void uniform_f32(u32 program_id, const char* uniform_name, f32 value) { glUniform1f(glGetUniformLocation(program_id, uniform_name), value); } -void uniform_i32(u32 program_id, const char *uniform_name, i32 value) { +void uniform_i32(u32 program_id, const char* uniform_name, i32 value) { glUniform1i(glGetUniformLocation(program_id, uniform_name), value); } -void uniform_mat4f(u32 program_id, const char *uniform_name, mat4 *value) { +void uniform_mat4f(u32 program_id, const char* uniform_name, mat4* value) { glUniformMatrix4fv(glGetUniformLocation(program_id, uniform_name), 1, GL_FALSE, value->data); } diff --git a/src/renderer/backends/opengl/backend_opengl.h b/src/renderer/backends/opengl/backend_opengl.h index 0ce765a..14a46f9 100644 --- a/src/renderer/backends/opengl/backend_opengl.h +++ b/src/renderer/backends/opengl/backend_opengl.h @@ -8,15 +8,24 @@ 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_device { +} gpu_device; +typedef struct gpu_pipeline_layout { + void *pad +} gpu_pipeline_layout; typedef struct gpu_pipeline { u32 shader_id; u32 pad; } gpu_pipeline; -typedef struct gpu_renderpass { void* pad } gpu_renderpass; -typedef struct gpu_cmd_encoder { void* pad } gpu_cmd_encoder; // Recording -typedef struct gpu_cmd_buffer { void* pad } gpu_cmd_buffer; // Ready for submission +typedef struct gpu_renderpass { + void *pad +} gpu_renderpass; +typedef struct gpu_cmd_encoder { + void *pad +} gpu_cmd_encoder; // Recording +typedef struct gpu_cmd_buffer { + void *pad +} gpu_cmd_buffer; // Ready for submission typedef struct gpu_buffer { union { @@ -25,8 +34,9 @@ typedef struct gpu_buffer { } id; u32 pad; } gpu_buffer; -typedef struct gpu_texture { void* pad } gpu_texture; - +typedef struct gpu_texture { + void *pad +} gpu_texture; u32 shader_create_separate(const char *vert_shader, const char *frag_shader); diff --git a/src/renderer/ral_types.h b/src/renderer/ral_types.h index 5cbf6fd..415796c 100644 --- a/src/renderer/ral_types.h +++ b/src/renderer/ral_types.h @@ -78,11 +78,8 @@ typedef enum gpu_buffer_type { } gpu_buffer_type; static const char* buffer_type_names[] = { - "RAL Buffer Default", - "RAL Buffer Vertex", - "RAL Buffer Index", - "RAL Buffer Uniform", - "RAL Buffer Count", + "RAL Buffer Default", "RAL Buffer Vertex", "RAL Buffer Index", + "RAL Buffer Uniform", "RAL Buffer Count", }; typedef enum gpu_buffer_flag { diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index aeedf85..63e5b29 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -15,9 +15,9 @@ #if defined(CEL_PLATFORM_WINDOWS) // #include "backend_dx11.h" #endif -#if defined (CEL_REND_BACKEND_VULKAN) +#if defined(CEL_REND_BACKEND_VULKAN) #include "backend_vulkan.h" -#elif defined (CEL_REND_BACKEND_OPENGL) +#elif defined(CEL_REND_BACKEND_OPENGL) #include "backend_opengl.h" #endif diff --git a/src/std/mem.c b/src/std/mem.c index a5a0b88..ede1db4 100644 --- a/src/std/mem.c +++ b/src/std/mem.c @@ -50,7 +50,7 @@ void_pool void_pool_create(arena* a, const char* debug_label, u64 capacity, u64 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 + assert(entry_size >= sizeof(void_pool_header)); // TODO: create my own assert with error message void_pool pool = { .capacity = capacity, .entry_size = entry_size, diff --git a/src/std/mem.h b/src/std/mem.h index b256e27..6e76763 100644 --- a/src/std/mem.h +++ b/src/std/mem.h @@ -69,7 +69,7 @@ void void_pool_dealloc(void_pool* pool, u32 raw_handle); } 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); \ + 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) { \ -- cgit v1.2.3-70-g09d2 From fc960d1f096332b30e6fa7694cf20849478d2b4d Mon Sep 17 00:00:00 2001 From: Omniscient Date: Fri, 7 Jun 2024 12:16:13 +1000 Subject: triangle verts werent const so make static instead --- examples/triangle/ex_triangle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/triangle/ex_triangle.c b/examples/triangle/ex_triangle.c index d57e224..a19cbb3 100644 --- a/examples/triangle/ex_triangle.c +++ b/examples/triangle/ex_triangle.c @@ -15,7 +15,7 @@ extern core g_core; -const custom_vertex vertices[] = { +static custom_vertex vertices[] = { (custom_vertex){ .pos = vec2(-0.5, -0.5), .color = vec3(1.0, 1.0, 1.0) }, (custom_vertex){ .pos = vec2(0.5, -0.5), .color = vec3(1.0, 0.0, 0.0) }, (custom_vertex){ .pos = vec2(-0.5, 0.5), .color = vec3(0.0, 0.0, 1.0) }, -- cgit v1.2.3-70-g09d2 From 4cbb8a9ec77620e6d3c0e4063b249e9cd8df46af Mon Sep 17 00:00:00 2001 From: Omniscient Date: Fri, 7 Jun 2024 12:22:50 +1000 Subject: what about this? --- examples/triangle/ex_triangle.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/triangle/ex_triangle.c b/examples/triangle/ex_triangle.c index a19cbb3..5b6fbea 100644 --- a/examples/triangle/ex_triangle.c +++ b/examples/triangle/ex_triangle.c @@ -15,15 +15,15 @@ extern core g_core; -static custom_vertex vertices[] = { - (custom_vertex){ .pos = vec2(-0.5, -0.5), .color = vec3(1.0, 1.0, 1.0) }, - (custom_vertex){ .pos = vec2(0.5, -0.5), .color = vec3(1.0, 0.0, 0.0) }, - (custom_vertex){ .pos = vec2(-0.5, 0.5), .color = vec3(0.0, 0.0, 1.0) }, - (custom_vertex){ .pos = vec2(0.5, 0.5), .color = vec3(0.0, 1.0, 0.0) }, -}; -const u32 indices[] = { 2, 1, 0, 1, 2, 3 }; - int main() { + custom_vertex vertices[] = { + (custom_vertex){ .pos = vec2(-0.5, -0.5), .color = vec3(1.0, 1.0, 1.0) }, + (custom_vertex){ .pos = vec2(0.5, -0.5), .color = vec3(1.0, 0.0, 0.0) }, + (custom_vertex){ .pos = vec2(-0.5, 0.5), .color = vec3(0.0, 0.0, 1.0) }, + (custom_vertex){ .pos = vec2(0.5, 0.5), .color = vec3(0.0, 1.0, 0.0) }, + }; + const u32 indices[] = { 2, 1, 0, 1, 2, 3 }; + core_bringup(); arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); -- cgit v1.2.3-70-g09d2 From 037cb840dfb90264cd1bef36736cefb3cf7f2dd9 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Fri, 7 Jun 2024 12:37:52 +1000 Subject: upload data when available on buffer creation --- src/renderer/backends/opengl/backend_opengl.c | 17 ++++++++++++++--- src/renderer/backends/opengl/backend_opengl.h | 3 ++- src/renderer/backends/opengl/opengl_helpers.h | 1 + 3 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 src/renderer/backends/opengl/opengl_helpers.h diff --git a/src/renderer/backends/opengl/backend_opengl.c b/src/renderer/backends/opengl/backend_opengl.c index 0cd2925..529a0d9 100644 --- a/src/renderer/backends/opengl/backend_opengl.c +++ b/src/renderer/backends/opengl/backend_opengl.c @@ -151,24 +151,35 @@ buffer_handle gpu_buffer_create(u64 size, gpu_buffer_type buf_type, gpu_buffer_f GLuint gl_buffer_id; glGenBuffers(1, &gl_buffer_id); + GLenum gl_buf_type; + switch (buf_type) { case CEL_BUFFER_UNIFORM: - glBindBuffer(GL_UNIFORM_BUFFER, gl_buffer_id); + gl_buf_type = GL_UNIFORM_BUFFER; break; case CEL_BUFFER_DEFAULT: case CEL_BUFFER_VERTEX: - glBindBuffer(GL_ARRAY_BUFFER, gl_buffer_id); + gl_buf_type = GL_ARRAY_BUFFER; break; case CEL_BUFFER_INDEX: - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl_buffer_id); + gl_buf_type = GL_ELEMENT_ARRAY_BUFFER; break; default: WARN("Unimplemented gpu_buffer_type provided %s", buffer_type_names[buf_type]); break; } + // bind buffer + glBindBuffer(gl_buf_type, gl_buffer_id); + // "allocating" the cpu-side buffer struct buffer_handle handle; gpu_buffer* buffer = buffer_pool_alloc(&context.resource_pools->buffers, &handle); + buffer->size = size; + + if (data) { + TRACE("Upload data as part of buffer creation"); + glBufferData(gl_buf_type, buffer->size, data, GL_STATIC_DRAW); + } return handle; } diff --git a/src/renderer/backends/opengl/backend_opengl.h b/src/renderer/backends/opengl/backend_opengl.h index 14a46f9..876cfe4 100644 --- a/src/renderer/backends/opengl/backend_opengl.h +++ b/src/renderer/backends/opengl/backend_opengl.h @@ -32,7 +32,8 @@ typedef struct gpu_buffer { u32 vbo; u32 ibo; } id; - u32 pad; + u32 vao; // Optional + u64 size; } gpu_buffer; typedef struct gpu_texture { void *pad diff --git a/src/renderer/backends/opengl/opengl_helpers.h b/src/renderer/backends/opengl/opengl_helpers.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/src/renderer/backends/opengl/opengl_helpers.h @@ -0,0 +1 @@ +#pragma once -- cgit v1.2.3-70-g09d2 From 19a5fae08d7f1f85cb5448a5f2b19f0f9d342a0e Mon Sep 17 00:00:00 2001 From: omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Sat, 8 Jun 2024 14:42:04 +1000 Subject: some more opengl work --- examples/triangle/ex_triangle.c | 10 ++++++-- src/renderer/backends/opengl/backend_opengl.c | 25 ++++++++++++++++++- src/renderer/backends/opengl/backend_opengl.h | 2 +- src/renderer/backends/opengl/opengl_helpers.h | 35 +++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/examples/triangle/ex_triangle.c b/examples/triangle/ex_triangle.c index 5b6fbea..0191c18 100644 --- a/examples/triangle/ex_triangle.c +++ b/examples/triangle/ex_triangle.c @@ -35,8 +35,14 @@ int main() { gpu_renderpass_desc pass_description = {}; gpu_renderpass* renderpass = gpu_renderpass_create(&pass_description); - str8 vert_path = str8lit("build/linux/x86_64/debug/triangle.vert.spv"); - str8 frag_path = str8lit("build/linux/x86_64/debug/triangle.frag.spv"); + str8 vert_path, frag_path; +#ifdef CEL_REND_BACKEND_OPENGL + vert_path = str8lit("assets/shaders/triangle.vert"); + frag_path = str8lit("assets/shaders/triangle.frag"); +#else + vert_path = str8lit("build/linux/x86_64/debug/triangle.vert.spv"); + frag_path = str8lit("build/linux/x86_64/debug/triangle.frag.spv"); +#endif 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) { diff --git a/src/renderer/backends/opengl/backend_opengl.c b/src/renderer/backends/opengl/backend_opengl.c index 529a0d9..8be1c2a 100644 --- a/src/renderer/backends/opengl/backend_opengl.c +++ b/src/renderer/backends/opengl/backend_opengl.c @@ -1,4 +1,6 @@ +#include #include "colours.h" +#include "opengl_helpers.h" #include "ral_types.h" #define CEL_REND_BACKEND_OPENGL #if defined(CEL_REND_BACKEND_OPENGL) @@ -27,6 +29,8 @@ static opengl_context context; struct GLFWwindow; +size_t vertex_attrib_size(vertex_attrib_type attr); + bool gpu_backend_init(const char* window_name, struct GLFWwindow* window) { INFO("loading OpenGL backend"); @@ -69,6 +73,24 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip u32 shader_id = shader_create_separate(description.vs.filepath.buf, description.fs.filepath.buf); pipeline->shader_id = shader_id; + // Vertex + u32 vao; + glGenVertexArrays(1, &vao); + pipeline->vao = vao; + + // Attributes + u32 attr_count = description.vertex_desc.attributes_count; + printf("N attributes %d\n", attr_count); + u64 offset = 0; + size_t vertex_size = description.vertex_desc.stride; + for (u32 i = 0; i < description.vertex_desc.attributes_count; i++) { + opengl_vertex_attr format = format_from_vertex_attr(description.vertex_desc.attributes[i]); + glVertexAttribPointer(i, format.count, format.data_type, GL_FALSE, vertex_size, (void*)offset); + size_t this_offset = format.count * vertex_attrib_size(description.vertex_desc.attributes[i]); + printf("offset total %lld this attr %ld\n", offset, this_offset); + offset += this_offset; + } + // Allocate uniform buffers if needed printf("data layouts %d\n", description.data_layouts_count); for (u32 layout_i = 0; layout_i < description.data_layouts_count; layout_i++) { @@ -129,6 +151,7 @@ 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) { // In OpenGL this is more or less equivalent to just setting the shader glUseProgram(pipeline->shader_id); + glBindVertexArray(pipeline->vao); } 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); @@ -177,7 +200,7 @@ buffer_handle gpu_buffer_create(u64 size, gpu_buffer_type buf_type, gpu_buffer_f buffer->size = size; if (data) { - TRACE("Upload data as part of buffer creation"); + TRACE("Upload data (%d bytes) as part of buffer creation", size); glBufferData(gl_buf_type, buffer->size, data, GL_STATIC_DRAW); } diff --git a/src/renderer/backends/opengl/backend_opengl.h b/src/renderer/backends/opengl/backend_opengl.h index 876cfe4..a9835c1 100644 --- a/src/renderer/backends/opengl/backend_opengl.h +++ b/src/renderer/backends/opengl/backend_opengl.h @@ -15,7 +15,7 @@ typedef struct gpu_pipeline_layout { } gpu_pipeline_layout; typedef struct gpu_pipeline { u32 shader_id; - u32 pad; + u32 vao; } gpu_pipeline; typedef struct gpu_renderpass { void *pad diff --git a/src/renderer/backends/opengl/opengl_helpers.h b/src/renderer/backends/opengl/opengl_helpers.h index 6f70f09..2f6bef3 100644 --- a/src/renderer/backends/opengl/opengl_helpers.h +++ b/src/renderer/backends/opengl/opengl_helpers.h @@ -1 +1,36 @@ #pragma once +#include "ral_types.h" +#include +#include +typedef struct opengl_vertex_attr { + u32 count; + GLenum data_type; +} opengl_vertex_attr ; +opengl_vertex_attr format_from_vertex_attr(vertex_attrib_type 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 VK_FORMAT_R32G32B32A32_SINT; + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 859ea7e23d2bbbc4b32b43727ae50aebe399e720 Mon Sep 17 00:00:00 2001 From: omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Sun, 9 Jun 2024 01:43:02 +1000 Subject: metal is back, baby --- assets/shaders/blinn_phong.vert | 2 +- assets/shaders/cube.frag | 2 +- assets/shaders/cube.vert | 2 +- assets/shaders/triangle.metal | 33 +++ assets/shaders/triangle.vert | 2 +- deps/Unity/extras/fixture/src/unity_fixture.c | 6 +- examples/cube/ex_cube.c | 4 +- examples/triangle/ex_triangle.c | 42 ++-- src/defines.h | 4 +- src/renderer/backends/backend_vulkan.c | 1 + src/renderer/backends/metal/backend_metal.h | 74 +++++++ src/renderer/backends/metal/backend_metal.m | 285 ++++++++++++++++++++++++++ src/renderer/backends/opengl/backend_opengl.c | 2 +- src/renderer/backends/opengl/opengl_helpers.h | 18 +- src/renderer/ral.c | 6 + src/renderer/ral.h | 3 +- src/renderer/render_types.h | 4 +- xmake.lua | 13 +- 18 files changed, 458 insertions(+), 45 deletions(-) create mode 100644 assets/shaders/triangle.metal create mode 100644 src/renderer/backends/metal/backend_metal.h create mode 100644 src/renderer/backends/metal/backend_metal.m diff --git a/assets/shaders/blinn_phong.vert b/assets/shaders/blinn_phong.vert index 1d2a53e..18609b7 100644 --- a/assets/shaders/blinn_phong.vert +++ b/assets/shaders/blinn_phong.vert @@ -1,4 +1,4 @@ -#version 430 core +#version 410 core struct Uniforms { mat4 model; diff --git a/assets/shaders/cube.frag b/assets/shaders/cube.frag index 292578f..88ba822 100644 --- a/assets/shaders/cube.frag +++ b/assets/shaders/cube.frag @@ -1,4 +1,4 @@ -#version 450 +#version 430 layout(location = 0) in vec3 fragColor; layout(location = 1) in vec2 fragTexCoord; diff --git a/assets/shaders/cube.vert b/assets/shaders/cube.vert index fa9f85b..2f1d76d 100644 --- a/assets/shaders/cube.vert +++ b/assets/shaders/cube.vert @@ -1,4 +1,4 @@ -#version 450 +#version 430 layout(binding = 0) uniform UniformBufferObject { mat4 model; diff --git a/assets/shaders/triangle.metal b/assets/shaders/triangle.metal new file mode 100644 index 0000000..6055705 --- /dev/null +++ b/assets/shaders/triangle.metal @@ -0,0 +1,33 @@ +#include + +using namespace metal; + +struct VertexIn { + float2 position; + float3 color; +}; + +struct VertexOut { + float4 computedPosition [[position]]; + float3 fragColor; +}; + +// Vertex shader +vertex VertexOut basic_vertex( + const device VertexIn* vertex_array [[ buffer(0) ]], + unsigned int vid [[ vertex_id ]] + ) { + VertexIn v = vertex_array[vid]; + + VertexOut outVertex = VertexOut(); + outVertex.computedPosition = float4(v.position.xy, 0.0, 1.0); + outVertex.fragColor = v.color; + return outVertex; +} + +// Fragment shader +fragment float4 basic_fragment( + VertexOut interpolated [[stage_in]] +) { + return float4(interpolated.fragColor, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/triangle.vert b/assets/shaders/triangle.vert index 8030561..f98696c 100644 --- a/assets/shaders/triangle.vert +++ b/assets/shaders/triangle.vert @@ -1,4 +1,4 @@ -#version 450 +#version 430 layout(location = 0) in vec2 inPos; layout(location = 1) in vec3 inColor; diff --git a/deps/Unity/extras/fixture/src/unity_fixture.c b/deps/Unity/extras/fixture/src/unity_fixture.c index e69b5a3..8ffe1f8 100644 --- a/deps/Unity/extras/fixture/src/unity_fixture.c +++ b/deps/Unity/extras/fixture/src/unity_fixture.c @@ -15,10 +15,8 @@ struct UNITY_FIXTURE_T UnityFixture; * Build with -D UNITY_OUTPUT_CHAR=outputChar and include * int (*outputChar)(int) = putchar; */ -void setUp(void) { /*does nothing*/ -} -void tearDown(void) { /*does nothing*/ -} +void setUp(void) { /*does nothing*/ } +void tearDown(void) { /*does nothing*/ } static void announceTestRun(unsigned int runNumber) { UnityPrint("Unity test run "); diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c index 7b0ab48..a3d5a9f 100644 --- a/examples/cube/ex_cube.c +++ b/examples/cube/ex_cube.c @@ -70,8 +70,8 @@ int main() { str8 vert_path, frag_path; #ifdef CEL_REND_BACKEND_OPENGL - vert_path = str8lit("assets/shaders/blinn_phong.vert"); - frag_path = str8lit("assets/shaders/blinn_phong.frag"); + vert_path = str8lit("assets/shaders/cube.vert"); + frag_path = str8lit("assets/shaders/cube.frag"); #else vert_path = str8lit("build/linux/x86_64/debug/cube.vert.spv"); frag_path = str8lit("build/linux/x86_64/debug/cube.frag.spv"); diff --git a/examples/triangle/ex_triangle.c b/examples/triangle/ex_triangle.c index 0191c18..d9954e6 100644 --- a/examples/triangle/ex_triangle.c +++ b/examples/triangle/ex_triangle.c @@ -36,12 +36,12 @@ int main() { gpu_renderpass* renderpass = gpu_renderpass_create(&pass_description); str8 vert_path, frag_path; -#ifdef CEL_REND_BACKEND_OPENGL +#if defined(CEL_REND_BACKEND_OPENGL) vert_path = str8lit("assets/shaders/triangle.vert"); frag_path = str8lit("assets/shaders/triangle.frag"); -#else - vert_path = str8lit("build/linux/x86_64/debug/triangle.vert.spv"); - frag_path = str8lit("build/linux/x86_64/debug/triangle.frag.spv"); +#elif defined(CEL_REND_BACKEND_METAL) + vert_path = str8lit("build/gfx.metallib"); + frag_path = str8lit("build/gfx.metallib"); #endif str8_opt vertex_shader = str8_from_file(&scratch, vert_path); str8_opt fragment_shader = str8_from_file(&scratch, frag_path); @@ -57,7 +57,11 @@ int main() { .vs = { .debug_name = "Triangle Vertex Shader", .filepath = vert_path, .code = vertex_shader.contents, - .is_spirv = true }, +#ifdef CEL_REND_BACKEND_METAL + .is_combined_vert_frag = true, +#endif + .is_spirv = true, + }, .fs = { .debug_name = "Triangle Fragment Shader", .filepath = frag_path, .code = fragment_shader.contents, @@ -75,7 +79,7 @@ int main() { buffer_handle triangle_index_buf = gpu_buffer_create(sizeof(indices), CEL_BUFFER_INDEX, CEL_BUFFER_FLAG_GPU, indices); - // Main loop + // // Main loop while (!should_exit()) { input_update(&g_core.input); @@ -83,24 +87,24 @@ int main() { continue; } gpu_cmd_encoder* enc = gpu_get_default_cmd_encoder(); - // Begin recording + // // Begin recording gpu_cmd_encoder_begin(*enc); gpu_cmd_encoder_begin_render(enc, renderpass); - encode_bind_pipeline(enc, PIPELINE_GRAPHICS, gfx_pipeline); - encode_set_default_settings(enc); + // encode_bind_pipeline(enc, PIPELINE_GRAPHICS, gfx_pipeline); + // encode_set_default_settings(enc); - // Record draw calls - encode_set_vertex_buffer(enc, triangle_vert_buf); - encode_set_index_buffer(enc, triangle_index_buf); - encode_draw_indexed(enc, 6); + // // Record draw calls + // encode_set_vertex_buffer(enc, triangle_vert_buf); + // encode_set_index_buffer(enc, triangle_index_buf); + // encode_draw_indexed(enc, 6); - // End recording - gpu_cmd_encoder_end_render(enc); + // // End recording + // gpu_cmd_encoder_end_render(enc); - gpu_cmd_buffer buf = gpu_cmd_encoder_finish( - enc); // Command buffer is no longer recording and is ready to submit - // Submit - gpu_queue_submit(&buf); + // gpu_cmd_buffer buf = gpu_cmd_encoder_finish(enc); // Command buffer is no longer recording + // and is ready to submit + // // Submit + // gpu_queue_submit(&buf); gpu_backend_end_frame(); } diff --git a/src/defines.h b/src/defines.h index a35dbf4..9050f25 100644 --- a/src/defines.h +++ b/src/defines.h @@ -77,6 +77,6 @@ Renderer backend defines: #endif #if defined(CEL_PLATFORM_MAC) -// #define CEL_REND_BACKEND_METAL 1 -#define CEL_REND_BACKEND_OPENGL 1 +#define CEL_REND_BACKEND_METAL 1 +// #define CEL_REND_BACKEND_OPENGL 1 #endif \ No newline at end of file diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index 06d8898..112e38b 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -403,6 +403,7 @@ VkFormat format_from_vertex_attr(vertex_attrib_type attr) { } 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); diff --git a/src/renderer/backends/metal/backend_metal.h b/src/renderer/backends/metal/backend_metal.h new file mode 100644 index 0000000..59b21d6 --- /dev/null +++ b/src/renderer/backends/metal/backend_metal.h @@ -0,0 +1,74 @@ +#pragma once +#define CEL_REND_BACKEND_METAL +#if defined(CEL_REND_BACKEND_METAL) + +#include "defines.h" +#include "maths_types.h" +#ifdef __OBJC__ +#import +#import +#import +#import +#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 id; + #else + void* id; + #endif +} gpu_device; +typedef struct gpu_pipeline_layout { + void* pad; +} gpu_pipeline_layout; +typedef struct gpu_pipeline { + #ifdef __OBJC__ + id 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 cmd_buffer; + id 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 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/renderer/backends/metal/backend_metal.m b/src/renderer/backends/metal/backend_metal.m new file mode 100644 index 0000000..0e9399e --- /dev/null +++ b/src/renderer/backends/metal/backend_metal.m @@ -0,0 +1,285 @@ +#include +#define CEL_REND_BACKEND_METAL +#if defined(CEL_REND_BACKEND_METAL) +#include +#include "ral_types.h" +#include "colours.h" +#include +#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 +#include + +#import +#import +#import +#import +#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 surface; + + id 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 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 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 gpu = MTLCreateSystemDefaultDevice(); + out_device->id = gpu; + context.device = out_device; + + const id 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 default_library = [context.device->id newLibraryWithFile:myNSString error:&err]; + assert(default_library); + + // setup vertex and fragment shaders + id ren_vert = [default_library newFunctionWithName:@"basic_vertex"]; + assert(ren_vert); + id 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 depth_descriptor = [context.device->id newDepthStencilStateWithDescriptor:depthStencilDescriptor]; + // FIXME: state->depth_state = depth_descriptor; + + id 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 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 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 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/renderer/backends/opengl/backend_opengl.c b/src/renderer/backends/opengl/backend_opengl.c index 8be1c2a..96415f1 100644 --- a/src/renderer/backends/opengl/backend_opengl.c +++ b/src/renderer/backends/opengl/backend_opengl.c @@ -2,7 +2,7 @@ #include "colours.h" #include "opengl_helpers.h" #include "ral_types.h" -#define CEL_REND_BACKEND_OPENGL +// #define CEL_REND_BACKEND_OPENGL #if defined(CEL_REND_BACKEND_OPENGL) #include #include "camera.h" diff --git a/src/renderer/backends/opengl/opengl_helpers.h b/src/renderer/backends/opengl/opengl_helpers.h index 2f6bef3..44d40cb 100644 --- a/src/renderer/backends/opengl/opengl_helpers.h +++ b/src/renderer/backends/opengl/opengl_helpers.h @@ -1,36 +1,36 @@ #pragma once -#include "ral_types.h" #include #include +#include "ral_types.h" typedef struct opengl_vertex_attr { u32 count; GLenum data_type; -} opengl_vertex_attr ; +} opengl_vertex_attr; opengl_vertex_attr format_from_vertex_attr(vertex_attrib_type attr) { switch (attr) { case ATTR_F32: - return (opengl_vertex_attr){.count = 1, .data_type = GL_FLOAT }; + return (opengl_vertex_attr){ .count = 1, .data_type = GL_FLOAT }; case ATTR_U32: - return (opengl_vertex_attr){.count = 1, .data_type = GL_UNSIGNED_INT }; + return (opengl_vertex_attr){ .count = 1, .data_type = GL_UNSIGNED_INT }; case ATTR_I32: - return (opengl_vertex_attr){.count = 1, .data_type = GL_INT }; + return (opengl_vertex_attr){ .count = 1, .data_type = GL_INT }; case ATTR_F32x2: - return (opengl_vertex_attr){.count = 2, .data_type = GL_FLOAT }; + 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 }; + 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 }; + return (opengl_vertex_attr){ .count = 4, .data_type = GL_FLOAT }; case ATTR_U32x4: // return VK_FORMAT_R32G32B32A32_UINT; case ATTR_I32x4: - // return VK_FORMAT_R32G32B32A32_SINT; + return (opengl_vertex_attr){ .count = 4, .data_type = GL_INT }; } } \ No newline at end of file diff --git a/src/renderer/ral.c b/src/renderer/ral.c index 4f2a999..fe12b4f 100644 --- a/src/renderer/ral.c +++ b/src/renderer/ral.c @@ -1,6 +1,12 @@ #include "ral.h" +#if defined(CEL_REND_BACKEND_VULKAN) +#include "backend_vulkan.h" +#elif defined(CEL_REND_BACKEND_METAL) +#include "backend_metal.h" +#elif defined(CEL_REND_BACKEND_OPENGL) #include "backend_opengl.h" +#endif size_t vertex_attrib_size(vertex_attrib_type attr) { switch (attr) { diff --git a/src/renderer/ral.h b/src/renderer/ral.h index a18ea87..3415b04 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -66,9 +66,10 @@ typedef enum pipeline_kind { typedef struct shader_desc { const char* debug_name; - str8 filepath; // where it came from + 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 } shader_desc; struct graphics_pipeline_desc { diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index 63e5b29..a2c35fe 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -17,12 +17,12 @@ #endif #if defined(CEL_REND_BACKEND_VULKAN) #include "backend_vulkan.h" +#elif defined(CEL_REND_BACKEND_METAL) +#include "backend_metal.h" #elif defined(CEL_REND_BACKEND_OPENGL) #include "backend_opengl.h" #endif -#include "backend_opengl.h" - struct GLFWwindow; /** @brief configuration passed to the renderer at init time */ diff --git a/xmake.lua b/xmake.lua index 5a2707c..86a673a 100644 --- a/xmake.lua +++ b/xmake.lua @@ -1,6 +1,6 @@ set_project("celeritas") set_version("0.1.0") -set_config("cc", "gcc") +set_config("cc", "clang") add_rules("mode.debug", "mode.release") -- we have two modes: debug & release @@ -30,6 +30,7 @@ elseif is_plat("windows") then elseif is_plat("macosx") then add_defines("CEL_PLATFORM_MAC") add_frameworks("Cocoa", "IOKit", "CoreVideo", "OpenGL") + add_frameworks( "Foundation", "Metal", "QuartzCore") set_runenv("MTL_DEBUG_LAYER", "1") -- add_syslinks("GL") end @@ -62,6 +63,7 @@ local core_sources = { "src/renderer/*.c", "src/renderer/backends/*.c", "src/renderer/backends/opengl/*.c", + "src/renderer/backends/metal/*.m", "src/resources/*.c", "src/std/*.c", "src/std/containers/*.c", @@ -113,6 +115,7 @@ target("core_config") add_includedirs("src/renderer/", {public = true}) add_includedirs("src/renderer/backends/", {public = true}) add_includedirs("src/renderer/backends/opengl", {public = true}) + add_includedirs("src/renderer/backends/metal", {public = true}) add_includedirs("src/resources/", {public = true}) add_includedirs("src/std/", {public = true}) add_includedirs("src/std/containers", {public = true}) @@ -166,6 +169,14 @@ target("tri") add_deps("core_static") add_files("examples/triangle/ex_triangle.c") set_rundir("$(projectdir)") + if is_plat("macosx") then + before_build(function (target) + print("build metal shaders lib") + os.exec("mkdir -p build/shaders") + os.exec("xcrun -sdk macosx metal -c assets/shaders/triangle.metal -o build/shaders/gfx.air") + os.exec("xcrun -sdk macosx metallib build/shaders/gfx.air -o build/gfx.metallib") + end) + end target("cube") set_kind("binary") -- cgit v1.2.3-70-g09d2 From 64830ce51a185091f54c2b42b365110d89d44f1b Mon Sep 17 00:00:00 2001 From: Omniscient Date: Sun, 9 Jun 2024 11:42:17 +1000 Subject: triangle on opengl works again. happy days --- assets/shaders/cube.frag | 3 +- assets/shaders/cube.vert | 3 +- assets/shaders/triangle.frag | 2 +- examples/triangle/ex_triangle.c | 31 ++-- src/renderer/backends/backend_vulkan.c | 8 +- src/renderer/backends/backend_vulkan.h | 2 +- src/renderer/backends/metal/backend_metal.h | 42 +++--- src/renderer/backends/opengl/backend_opengl.c | 204 +++++++++----------------- src/renderer/backends/opengl/backend_opengl.h | 9 +- src/renderer/backends/opengl/opengl_helpers.h | 43 +++++- src/renderer/ral.c | 7 +- src/renderer/ral.h | 9 +- src/renderer/ral_types.h | 6 + src/renderer/render_types.h | 1 + xmake.lua | 6 +- 15 files changed, 192 insertions(+), 184 deletions(-) diff --git a/assets/shaders/cube.frag b/assets/shaders/cube.frag index 88ba822..796f1c8 100644 --- a/assets/shaders/cube.frag +++ b/assets/shaders/cube.frag @@ -8,5 +8,6 @@ layout(binding = 1) uniform sampler2D texSampler; layout(location = 0) out vec4 outColor; void main() { - outColor = texture(texSampler, fragTexCoord); // vec4(fragTexCoord, 0.0); + // outColor = texture(texSampler, fragTexCoord); // vec4(fragTexCoord, 0.0); + outColor = vec4(1.0); } diff --git a/assets/shaders/cube.vert b/assets/shaders/cube.vert index 2f1d76d..57475e7 100644 --- a/assets/shaders/cube.vert +++ b/assets/shaders/cube.vert @@ -1,6 +1,6 @@ #version 430 -layout(binding = 0) uniform UniformBufferObject { +layout(binding = 0) uniform Matrices { mat4 model; mat4 view; mat4 proj; @@ -15,6 +15,7 @@ layout(location = 1) out vec2 fragTexCoord; void main() { gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0); + // gl_Position = vec4(inPosition, 1.0); fragColor = abs(inNormal); fragTexCoord = inTexCoords; } diff --git a/assets/shaders/triangle.frag b/assets/shaders/triangle.frag index c3ff328..ad6de8e 100644 --- a/assets/shaders/triangle.frag +++ b/assets/shaders/triangle.frag @@ -1,4 +1,4 @@ -#version 450 +#version 430 layout(location = 0) in vec3 fragColor; layout(location = 0) out vec4 outColor; diff --git a/examples/triangle/ex_triangle.c b/examples/triangle/ex_triangle.c index d9954e6..cd401c7 100644 --- a/examples/triangle/ex_triangle.c +++ b/examples/triangle/ex_triangle.c @@ -4,6 +4,7 @@ #include "buf.h" #include "camera.h" #include "core.h" +#include "defines.h" #include "file.h" #include "log.h" #include "maths.h" @@ -73,8 +74,8 @@ int main() { gpu_pipeline* gfx_pipeline = gpu_graphics_pipeline_create(pipeline_description); // Load triangle vertex and index data - buffer_handle triangle_vert_buf = - gpu_buffer_create(4 * sizeof(vertex), CEL_BUFFER_VERTEX, CEL_BUFFER_FLAG_GPU, vertices); + buffer_handle triangle_vert_buf = gpu_buffer_create(4 * sizeof(custom_vertex), CEL_BUFFER_VERTEX, + CEL_BUFFER_FLAG_GPU, vertices); buffer_handle triangle_index_buf = gpu_buffer_create(sizeof(indices), CEL_BUFFER_INDEX, CEL_BUFFER_FLAG_GPU, indices); @@ -87,24 +88,24 @@ int main() { continue; } gpu_cmd_encoder* enc = gpu_get_default_cmd_encoder(); - // // Begin recording + // // Begin recording gpu_cmd_encoder_begin(*enc); gpu_cmd_encoder_begin_render(enc, renderpass); - // encode_bind_pipeline(enc, PIPELINE_GRAPHICS, gfx_pipeline); - // encode_set_default_settings(enc); + encode_bind_pipeline(enc, PIPELINE_GRAPHICS, gfx_pipeline); + encode_set_default_settings(enc); - // // Record draw calls - // encode_set_vertex_buffer(enc, triangle_vert_buf); - // encode_set_index_buffer(enc, triangle_index_buf); - // encode_draw_indexed(enc, 6); + // // Record draw calls + encode_set_vertex_buffer(enc, triangle_vert_buf); + encode_set_index_buffer(enc, triangle_index_buf); + encode_draw_indexed(enc, 6); - // // End recording - // gpu_cmd_encoder_end_render(enc); + // // End recording + // gpu_cmd_encoder_end_render(enc); - // gpu_cmd_buffer buf = gpu_cmd_encoder_finish(enc); // Command buffer is no longer recording - // and is ready to submit - // // Submit - // gpu_queue_submit(&buf); + // gpu_cmd_buffer buf = gpu_cmd_encoder_finish(enc); // Command buffer is no longer recording + // and is ready to submit + // // Submit + // gpu_queue_submit(&buf); gpu_backend_end_frame(); } diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index 112e38b..8801230 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -1,7 +1,10 @@ +#include "defines.h" #if defined(CEL_REND_BACKEND_VULKAN) -#include +#define GLFW_INCLUDE_VULKAN #include + +#include #include #include #include @@ -19,7 +22,6 @@ #include "str.h" #include "vulkan_helpers.h" -#include "defines.h" #include "file.h" #include "log.h" #include "ral.h" @@ -1637,7 +1639,7 @@ texture_handle gpu_texture_create(texture_desc desc, bool create_view, const voi &texture->sampler); if (res != VK_SUCCESS) { ERROR("Error creating texture sampler for image %s", texture->debug_label); - return; + exit(1); } return handle; diff --git a/src/renderer/backends/backend_vulkan.h b/src/renderer/backends/backend_vulkan.h index 21a80ba..6ca0bb5 100644 --- a/src/renderer/backends/backend_vulkan.h +++ b/src/renderer/backends/backend_vulkan.h @@ -1,10 +1,10 @@ #pragma once +#include "defines.h" #if defined(CEL_REND_BACKEND_VULKAN) #include #include #include -#include "defines.h" #include "mem.h" #include "ral.h" #include "ral_types.h" diff --git a/src/renderer/backends/metal/backend_metal.h b/src/renderer/backends/metal/backend_metal.h index 59b21d6..9561bb6 100644 --- a/src/renderer/backends/metal/backend_metal.h +++ b/src/renderer/backends/metal/backend_metal.h @@ -1,70 +1,70 @@ #pragma once -#define CEL_REND_BACKEND_METAL +// #define CEL_REND_BACKEND_METAL #if defined(CEL_REND_BACKEND_METAL) #include "defines.h" #include "maths_types.h" #ifdef __OBJC__ +#import #import #import #import -#import #else typedef void* id; #endif typedef struct gpu_swapchain { u32x2 dimensions; - #ifdef __OBJC__ +#ifdef __OBJC__ CAMetalLayer* swapchain; - #else +#else void* swapchain; - #endif +#endif } gpu_swapchain; typedef struct gpu_device { - /** @brief `device` gives us access to our GPU */ - #ifdef __OBJC__ +/** @brief `device` gives us access to our GPU */ +#ifdef __OBJC__ id id; - #else +#else void* id; - #endif +#endif } gpu_device; typedef struct gpu_pipeline_layout { void* pad; } gpu_pipeline_layout; typedef struct gpu_pipeline { - #ifdef __OBJC__ +#ifdef __OBJC__ id pipeline_state; - #else +#else void* pipeline_state; - #endif +#endif } gpu_pipeline; typedef struct gpu_renderpass { - #ifdef __OBJC__ +#ifdef __OBJC__ MTLRenderPassDescriptor* rpass_descriptor; - #else +#else void* rpass_descriptor; - #endif +#endif } gpu_renderpass; typedef struct gpu_cmd_encoder { - #ifdef __OBJC__ +#ifdef __OBJC__ id cmd_buffer; id render_encoder; - #else +#else void* cmd_buffer; void* render_encoder; - #endif +#endif } gpu_cmd_encoder; typedef struct gpu_cmd_buffer { void* pad; } gpu_cmd_buffer; typedef struct gpu_buffer { - #ifdef __OBJC__ +#ifdef __OBJC__ id id; - #else +#else void* id; - #endif +#endif u64 size; } gpu_buffer; typedef struct gpu_texture { diff --git a/src/renderer/backends/opengl/backend_opengl.c b/src/renderer/backends/opengl/backend_opengl.c index 96415f1..073f343 100644 --- a/src/renderer/backends/opengl/backend_opengl.c +++ b/src/renderer/backends/opengl/backend_opengl.c @@ -2,8 +2,9 @@ #include "colours.h" #include "opengl_helpers.h" #include "ral_types.h" -// #define CEL_REND_BACKEND_OPENGL +#define CEL_REND_BACKEND_OPENGL 1 #if defined(CEL_REND_BACKEND_OPENGL) +#include #include #include "camera.h" @@ -29,8 +30,6 @@ static opengl_context context; struct GLFWwindow; -size_t vertex_attrib_size(vertex_attrib_type attr); - bool gpu_backend_init(const char* window_name, struct GLFWwindow* window) { INFO("loading OpenGL backend"); @@ -62,7 +61,7 @@ bool gpu_backend_init(const char* window_name, struct GLFWwindow* window) { void gpu_backend_shutdown() {} -bool gpu_device_create(gpu_device* out_device) {} +bool gpu_device_create(gpu_device* out_device) { /* No-op in OpenGL */ } void gpu_device_destroy() {} // --- Render Pipeline @@ -73,23 +72,8 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip u32 shader_id = shader_create_separate(description.vs.filepath.buf, description.fs.filepath.buf); pipeline->shader_id = shader_id; - // Vertex - u32 vao; - glGenVertexArrays(1, &vao); - pipeline->vao = vao; - - // Attributes - u32 attr_count = description.vertex_desc.attributes_count; - printf("N attributes %d\n", attr_count); - u64 offset = 0; - size_t vertex_size = description.vertex_desc.stride; - for (u32 i = 0; i < description.vertex_desc.attributes_count; i++) { - opengl_vertex_attr format = format_from_vertex_attr(description.vertex_desc.attributes[i]); - glVertexAttribPointer(i, format.count, format.data_type, GL_FALSE, vertex_size, (void*)offset); - size_t this_offset = format.count * vertex_attrib_size(description.vertex_desc.attributes[i]); - printf("offset total %lld this attr %ld\n", offset, this_offset); - offset += this_offset; - } + // Vertex format + pipeline->vertex_desc = description.vertex_desc; // Allocate uniform buffers if needed printf("data layouts %d\n", description.data_layouts_count); @@ -98,6 +82,20 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip 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) { + 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[binding_id] = ubo_handle; + gpu_buffer* ubo_buf = BUFFER_GET(ubo_handle); + glBindBuffer(GL_UNIFORM_BUFFER, ubo_buf->id.ubo); + glBindBufferBase(GL_UNIFORM_BUFFER, binding_j, ubo_buf->id.ubo); + + // Now we want to store a handle associated with the shader for this + } } } @@ -139,7 +137,10 @@ 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) {} /** @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) {} +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, @@ -149,43 +150,77 @@ 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; // In OpenGL this is more or less equivalent to just setting the shader glUseProgram(pipeline->shader_id); - glBindVertexArray(pipeline->vao); } 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); - size_t binding_count = sdl.bindings_count; 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 = encoder->pipeline->uniform_bindings[i]; + gpu_buffer* ubo_buf = BUFFER_GET(b); + glBindBuffer(GL_UNIFORM_BUFFER, ubo_buf->id.ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, ubo_buf->size, data->data); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } } } void encode_set_default_settings(gpu_cmd_encoder* encoder) {} -void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) {} -void encode_set_index_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) {} -void encode_draw(gpu_cmd_encoder* encoder) {} -void encode_draw_indexed(gpu_cmd_encoder* encoder, u64 index_count) {} +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 + 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) { + 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]); @@ -194,27 +229,22 @@ buffer_handle gpu_buffer_create(u64 size, gpu_buffer_type buf_type, gpu_buffer_f // bind buffer glBindBuffer(gl_buf_type, gl_buffer_id); - // "allocating" the cpu-side buffer struct - buffer_handle handle; - gpu_buffer* buffer = buffer_pool_alloc(&context.resource_pools->buffers, &handle); - buffer->size = size; - if (data) { TRACE("Upload data (%d bytes) as part of buffer creation", size); - glBufferData(gl_buf_type, buffer->size, data, GL_STATIC_DRAW); + glBufferData(gl_buf_type, buffer->size, data, gl_buf_usage); + } else { + TRACE("Allocating the correct size anyway"); + glBufferData(gl_buf_type, buffer->size, NULL, gl_buf_usage); } + glBindBuffer(gl_buf_type, 0); + return handle; } void gpu_buffer_destroy(buffer_handle buffer) {} void gpu_buffer_upload(const void* data) {} -// Textures -/** @brief Create a new GPU texture resource. - * @param create_view creates a texture view (with same dimensions) at the same time - * @param data if not NULL then the data stored at the pointer will be uploaded to the GPU texture - * @note automatically creates a sampler for you */ 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) {} @@ -279,48 +309,16 @@ u32 shader_create_separate(const char* vert_shader, const char* frag_shader) { return shader_prog; } -// /** @brief Internal backend state */ -// typedef struct opengl_state { -// } opengl_state; - -// bool gfx_backend_init(renderer *ren) { -// INFO("loading OpenGL backend"); - -// // glfwInit(); // Already handled in `renderer_init` -// 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); - -// opengl_state *internal = malloc(sizeof(opengl_state)); -// ren->backend_context = (void *)internal; - -// return true; -// } - -// void gfx_backend_draw_frame(renderer *ren, camera *cam, mat4 model, texture *tex) {} - -// void gfx_backend_shutdown(renderer *ren) {} - -void uniform_vec3f(u32 program_id, const char* uniform_name, vec3* value) { +inline void uniform_vec3f(u32 program_id, const char* uniform_name, vec3* value) { glUniform3fv(glGetUniformLocation(program_id, uniform_name), 1, &value->x); } -void uniform_f32(u32 program_id, const char* uniform_name, f32 value) { +inline void uniform_f32(u32 program_id, const char* uniform_name, f32 value) { glUniform1f(glGetUniformLocation(program_id, uniform_name), value); } -void uniform_i32(u32 program_id, const char* uniform_name, i32 value) { +inline void uniform_i32(u32 program_id, const char* uniform_name, i32 value) { glUniform1i(glGetUniformLocation(program_id, uniform_name), value); } -void uniform_mat4f(u32 program_id, const char* uniform_name, mat4* 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); } @@ -377,60 +375,4 @@ void uniform_mat4f(u32 program_id, const char* uniform_name, mat4* value) { // u32 gl_primitive = to_gl_prim_topology(primitive); // glDrawArrays(gl_primitive, start_index, count); // } - -// shader 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); - -// shader s = { .program_id = shader_prog }; -// return s; -// } - -// void set_shader(shader s) { glUseProgram(s.program_id); } - #endif diff --git a/src/renderer/backends/opengl/backend_opengl.h b/src/renderer/backends/opengl/backend_opengl.h index a9835c1..91de38d 100644 --- a/src/renderer/backends/opengl/backend_opengl.h +++ b/src/renderer/backends/opengl/backend_opengl.h @@ -4,6 +4,9 @@ #include "defines.h" #include "maths_types.h" +#include "ral_types.h" + +#define MAX_PIPELINE_UNIFORM_BUFFERS 32 typedef struct gpu_swapchain { u32x2 dimensions; @@ -15,13 +18,14 @@ typedef struct gpu_pipeline_layout { } gpu_pipeline_layout; typedef struct gpu_pipeline { u32 shader_id; - u32 vao; + vertex_description vertex_desc; + buffer_handle uniform_bindings[MAX_PIPELINE_UNIFORM_BUFFERS]; } gpu_pipeline; typedef struct gpu_renderpass { void *pad } gpu_renderpass; typedef struct gpu_cmd_encoder { - void *pad + gpu_pipeline *pipeline; } gpu_cmd_encoder; // Recording typedef struct gpu_cmd_buffer { void *pad @@ -31,6 +35,7 @@ typedef struct gpu_buffer { union { u32 vbo; u32 ibo; + u32 ubo; } id; u32 vao; // Optional u64 size; diff --git a/src/renderer/backends/opengl/opengl_helpers.h b/src/renderer/backends/opengl/opengl_helpers.h index 44d40cb..405a8f1 100644 --- a/src/renderer/backends/opengl/opengl_helpers.h +++ b/src/renderer/backends/opengl/opengl_helpers.h @@ -1,4 +1,10 @@ +#if defined(CEL_REND_BACKEND_OPENGL) #pragma once +#include "backend_opengl.h" +#include "log.h" +#include "ral.h" +#include "ral_types.h" + #include #include #include "ral_types.h" @@ -6,7 +12,8 @@ typedef struct opengl_vertex_attr { u32 count; GLenum data_type; } opengl_vertex_attr; -opengl_vertex_attr format_from_vertex_attr(vertex_attrib_type attr) { + +static opengl_vertex_attr format_from_vertex_attr(vertex_attrib_type attr) { switch (attr) { case ATTR_F32: return (opengl_vertex_attr){ .count = 1, .data_type = GL_FLOAT }; @@ -31,6 +38,36 @@ opengl_vertex_attr format_from_vertex_attr(vertex_attrib_type attr) { case ATTR_U32x4: // return VK_FORMAT_R32G32B32A32_UINT; case ATTR_I32x4: - return (opengl_vertex_attr){ .count = 4, .data_type = GL_INT }; + return (opengl_vertex_attr){ .count = 4, .data_type = GL_INT }; + } +} + +static u32 opengl_bindcreate_vao(gpu_buffer* buf, vertex_description desc) { + // 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.stride; + 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 = vertex_attrib_size(desc.attributes[i]); + printf("offset total %lld this attr %ld\n", offset, this_offset); + offset += this_offset; } -} \ No newline at end of file + glBindBuffer(GL_ARRAY_BUFFER, 0); + + return vao; +} + +#endif diff --git a/src/renderer/ral.c b/src/renderer/ral.c index fe12b4f..123c932 100644 --- a/src/renderer/ral.c +++ b/src/renderer/ral.c @@ -68,4 +68,9 @@ void resource_pools_init(arena* a, struct resource_pools* res_pools) { res_pools->textures = tex_pool; // context.resource_pools = res_pools; -} \ No newline at end of file +} + +void print_shader_binding(shader_binding b) { + printf("Binding name: %s type %s vis %d stores data %d\n", b.label, + shader_binding_type_name[b.type], b.vis, b.stores_data); +} diff --git a/src/renderer/ral.h b/src/renderer/ral.h index 3415b04..067847b 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -44,6 +44,10 @@ TYPED_POOL(gpu_pipeline_layout, pipeline_layout); 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)) + // --- Pools typedef struct gpu_backend_pools { pipeline_pool pipelines; @@ -69,7 +73,7 @@ typedef struct shader_desc { 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 + bool is_combined_vert_frag; // Contains both vertex and fragment stages } shader_desc; struct graphics_pipeline_desc { @@ -149,7 +153,7 @@ void encode_set_default_settings(gpu_cmd_encoder* encoder); void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf); void encode_set_index_buffer(gpu_cmd_encoder* encoder, buffer_handle buf); void encode_set_bind_group(); // TODO -void encode_draw(gpu_cmd_encoder* encoder); +void encode_draw(gpu_cmd_encoder* encoder, u64 count); void encode_draw_indexed(gpu_cmd_encoder* encoder, u64 index_count); void encode_clear_buffer(gpu_cmd_encoder* encoder, buffer_handle buf); @@ -182,3 +186,4 @@ void gpu_temp_draw(size_t n_verts); // --- Helpers vertex_description static_3d_vertex_description(); +size_t vertex_attrib_size(vertex_attrib_type attr); diff --git a/src/renderer/ral_types.h b/src/renderer/ral_types.h index 415796c..f1f7809 100644 --- a/src/renderer/ral_types.h +++ b/src/renderer/ral_types.h @@ -201,6 +201,10 @@ typedef enum shader_binding_type { SHADER_BINDING_COUNT } shader_binding_type; +static const char* shader_binding_type_name[] = { "BUFFER", "BUFFER ARRAY", "TEXTURE", + "TEXTURE ARRAY", "SAMPLER", "BYTES", + "COUNT" }; + // pub trait ShaderBindable: Clone + Copy { // fn bind_to(&self, context: &mut PipelineContext, index: u32); // } @@ -228,6 +232,8 @@ typedef struct shader_binding { #define MAX_LAYOUT_BINDINGS 8 +void print_shader_binding(shader_binding b); + /** @brief A list of bindings that describe what data a shader / pipeline expects @note This roughly correlates to a descriptor set layout in Vulkan */ diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index a2c35fe..349f65a 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -10,6 +10,7 @@ */ #pragma once +#include "defines.h" #include "ral.h" #include "ral_types.h" #if defined(CEL_PLATFORM_WINDOWS) diff --git a/xmake.lua b/xmake.lua index 86a673a..6af1402 100644 --- a/xmake.lua +++ b/xmake.lua @@ -20,7 +20,7 @@ end -- Platform defines and system packages if is_plat("linux") then add_defines("CEL_PLATFORM_LINUX") - add_syslinks("dl", "X11", "pthread") + add_syslinks("dl", "X11", "pthread", "vulkan") elseif is_plat("windows") then add_defines("CEL_PLATFORM_WINDOWS") add_syslinks("user32", "gdi32", "kernel32", "shell32") @@ -63,7 +63,6 @@ local core_sources = { "src/renderer/*.c", "src/renderer/backends/*.c", "src/renderer/backends/opengl/*.c", - "src/renderer/backends/metal/*.m", "src/resources/*.c", "src/std/*.c", "src/std/containers/*.c", @@ -133,6 +132,9 @@ target("core_config") add_linkdirs("$(env VULKAN_SDK)/Lib", {public = true}) add_links("vulkan-1") end + if is_plat("macosx") then + add_files("src/renderer/backends/metal/*.m") + end set_default(false) -- prevents standalone building of this target target("core_static") -- cgit v1.2.3-70-g09d2 From d4ff15d9cd82a6e3bc71da9d04ee0f250460cef1 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Sun, 9 Jun 2024 14:55:53 +1000 Subject: fix cube --- assets/shaders/cube.frag | 2 +- assets/shaders/cube.vert | 8 ++++-- examples/cube/ex_cube.c | 16 ++++++++--- src/maths/maths.h | 1 + src/renderer/backends/opengl/backend_opengl.c | 39 ++++++++++++++++++--------- src/renderer/backends/opengl/opengl_helpers.h | 2 +- src/renderer/render.c | 1 + 7 files changed, 49 insertions(+), 20 deletions(-) diff --git a/assets/shaders/cube.frag b/assets/shaders/cube.frag index 796f1c8..9d8ab28 100644 --- a/assets/shaders/cube.frag +++ b/assets/shaders/cube.frag @@ -9,5 +9,5 @@ layout(location = 0) out vec4 outColor; void main() { // outColor = texture(texSampler, fragTexCoord); // vec4(fragTexCoord, 0.0); - outColor = vec4(1.0); + outColor = vec4(fragColor, 1.0); } diff --git a/assets/shaders/cube.vert b/assets/shaders/cube.vert index 57475e7..e7d6a79 100644 --- a/assets/shaders/cube.vert +++ b/assets/shaders/cube.vert @@ -1,10 +1,13 @@ #version 430 -layout(binding = 0) uniform Matrices { +layout( binding = 0) uniform Matrices { mat4 model; mat4 view; mat4 proj; } ubo; +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inNormal; @@ -14,7 +17,8 @@ layout(location = 0) out vec3 fragColor; layout(location = 1) out vec2 fragTexCoord; void main() { - gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0); + // gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0); + gl_Position = projection * view * model * vec4(inPosition, 1.0); // gl_Position = vec4(inPosition, 1.0); fragColor = abs(inNormal); fragTexCoord = inTexCoords; diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c index a3d5a9f..e85b5c1 100644 --- a/examples/cube/ex_cube.c +++ b/examples/cube/ex_cube.c @@ -62,6 +62,7 @@ int main() { vertex_desc_add(&vertex_input, "inPosition", ATTR_F32x3); vertex_desc_add(&vertex_input, "inNormal", ATTR_F32x3); vertex_desc_add(&vertex_input, "inTexCoords", ATTR_F32x2); + vertex_input.use_full_vertex_size = true; shader_data mvp_uniforms_data = { .data = NULL, .shader_data_get_layout = &mvp_uniforms_layout }; @@ -129,14 +130,23 @@ int main() { transform transform = { .position = vec3(-0.5, -0.5, -0.5), .rotation = quat_from_axis_angle(VEC3_Y, theta, true), .scale = 1.0 }; + /* INFO("Swapchain dimensions x %d y %d", g_core.renderer.swapchain.dimensions.x, + * g_core.renderer.swapchain.dimensions.y); */ + mat4 model = transform_to_mat(&transform); mat4 view, proj; - camera_view_projection(&cam, g_core.renderer.swapchain.dimensions.x, - g_core.renderer.swapchain.dimensions.y, &view, &proj); + camera_view_projection(&cam, 1000, 1000, + /* g_core.renderer.swapchain.dimensions.x, */ + /* g_core.renderer.swapchain.dimensions.y, */ + &view, &proj); mvp_uniforms mvp_data = { .model = model, .view = view, .projection = proj }; my_shader_bind_group shader_bind_data = { .mvp = mvp_data, .tex = texture }; mvp_uniforms_data.data = &shader_bind_data; - encode_bind_shader_data(enc, 0, &mvp_uniforms_data); + /* encode_bind_shader_data(enc, 0, &mvp_uniforms_data); */ + + uniform_mat4f(enc->pipeline->shader_id, "model", &model); + uniform_mat4f(enc->pipeline->shader_id, "view", &view); + uniform_mat4f(enc->pipeline->shader_id, "projection", &proj); // Record draw calls draw_mesh(&cube, &model); diff --git a/src/maths/maths.h b/src/maths/maths.h index 217f2e0..45d69c1 100644 --- a/src/maths/maths.h +++ b/src/maths/maths.h @@ -10,6 +10,7 @@ #include #include +#include "defines.h" #include "maths_types.h" // --- Helpers diff --git a/src/renderer/backends/opengl/backend_opengl.c b/src/renderer/backends/opengl/backend_opengl.c index 073f343..17587a2 100644 --- a/src/renderer/backends/opengl/backend_opengl.c +++ b/src/renderer/backends/opengl/backend_opengl.c @@ -1,12 +1,11 @@ #include +#include #include "colours.h" #include "opengl_helpers.h" #include "ral_types.h" -#define CEL_REND_BACKEND_OPENGL 1 #if defined(CEL_REND_BACKEND_OPENGL) #include #include -#include "camera.h" #include "backend_opengl.h" #include "defines.h" @@ -55,6 +54,7 @@ bool gpu_backend_init(const char* window_name, struct GLFWwindow* window) { } glEnable(GL_DEPTH_TEST); + // glFrontFace(GL_CW); return true; } @@ -62,7 +62,7 @@ bool gpu_backend_init(const char* window_name, struct GLFWwindow* window) { void gpu_backend_shutdown() {} bool gpu_device_create(gpu_device* out_device) { /* No-op in OpenGL */ } -void gpu_device_destroy() {} +void gpu_device_destroy() { /* No-op in OpenGL */ } // --- Render Pipeline gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description) { @@ -91,8 +91,20 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip NULL); // no data right now pipeline->uniform_bindings[binding_id] = ubo_handle; gpu_buffer* ubo_buf = BUFFER_GET(ubo_handle); + + u32 blockIndex = glGetUniformBlockIndex(pipeline->shader_id, "Matrices"); + printf("Block index for Matrices: %d", blockIndex); + u32 blocksize; + glGetActiveUniformBlockiv(pipeline->shader_id, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, + &blocksize); + printf("\t with size %d bytes\n", blocksize); + glBindBuffer(GL_UNIFORM_BUFFER, ubo_buf->id.ubo); glBindBufferBase(GL_UNIFORM_BUFFER, binding_j, ubo_buf->id.ubo); + if (blockIndex != GL_INVALID_INDEX) { + printf("Here\n"); + glUniformBlockBinding(pipeline->shader_id, blockIndex, 0); + } // Now we want to store a handle associated with the shader for this } @@ -151,7 +163,7 @@ 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; - // In OpenGL this is more or less equivalent to just setting the shader + // 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) { @@ -159,14 +171,16 @@ void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* d for (u32 i = 0; i < sdl.bindings_count; i++) { shader_binding binding = sdl.bindings[i]; - print_shader_binding(binding); + /* print_shader_binding(binding); */ if (binding.type == SHADER_BINDING_BYTES) { buffer_handle b = encoder->pipeline->uniform_bindings[i]; gpu_buffer* ubo_buf = BUFFER_GET(b); glBindBuffer(GL_UNIFORM_BUFFER, ubo_buf->id.ubo); glBufferSubData(GL_UNIFORM_BUFFER, 0, ubo_buf->size, data->data); - glBindBuffer(GL_UNIFORM_BUFFER, 0); + /* printf("Size %d\n", ubo_buf->size); */ + + /* glBindBuffer(GL_UNIFORM_BUFFER, 0); */ } } } @@ -174,6 +188,7 @@ 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); @@ -208,7 +223,7 @@ buffer_handle gpu_buffer_create(u64 size, gpu_buffer_type buf_type, gpu_buffer_f case CEL_BUFFER_UNIFORM: DEBUG("Creating Uniform buffer"); gl_buf_type = GL_UNIFORM_BUFFER; - gl_buf_usage = GL_DYNAMIC_DRAW; + /* gl_buf_usage = GL_DYNAMIC_DRAW; */ buffer->id.ubo = gl_buffer_id; break; case CEL_BUFFER_DEFAULT: @@ -254,7 +269,10 @@ bytebuffer vertices_as_bytebuffer(arena* a, vertex_format format, vertex_darray* // --- TEMP bool gpu_backend_begin_frame() { return true; } -void gpu_backend_end_frame() { glfwSwapBuffers(context.window); } +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) { @@ -370,9 +388,4 @@ inline void uniform_mat4f(u32 program_id, const char* uniform_name, mat4* value) // break; // } // } - -// void draw_primitives(cel_primitive_topology primitive, u32 start_index, u32 count) { -// u32 gl_primitive = to_gl_prim_topology(primitive); -// glDrawArrays(gl_primitive, start_index, count); -// } #endif diff --git a/src/renderer/backends/opengl/opengl_helpers.h b/src/renderer/backends/opengl/opengl_helpers.h index 405a8f1..a3c4014 100644 --- a/src/renderer/backends/opengl/opengl_helpers.h +++ b/src/renderer/backends/opengl/opengl_helpers.h @@ -54,7 +54,7 @@ static u32 opengl_bindcreate_vao(gpu_buffer* buf, vertex_description desc) { u32 attr_count = desc.attributes_count; printf("N attributes %d\n", attr_count); u64 offset = 0; - size_t vertex_size = desc.stride; + size_t vertex_size = desc.use_full_vertex_size ? sizeof(vertex) : desc.stride; 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); diff --git a/src/renderer/render.c b/src/renderer/render.c index 5723c9e..7833ac9 100644 --- a/src/renderer/render.c +++ b/src/renderer/render.c @@ -161,6 +161,7 @@ void draw_mesh(mesh* mesh, mat4* model) { // , mat4* view, mat4* proj) { } // Assume this has already been done /* encode_bind_shader_data(enc, 0, &mvp_uniforms_data); */ + encode_draw_indexed(enc, mesh->index_count); } -- cgit v1.2.3-70-g09d2