diff options
-rw-r--r-- | assets/shaders/cube.frag | 3 | ||||
-rw-r--r-- | assets/shaders/cube.vert | 3 | ||||
-rw-r--r-- | assets/shaders/triangle.frag | 2 | ||||
-rw-r--r-- | examples/triangle/ex_triangle.c | 31 | ||||
-rw-r--r-- | src/renderer/backends/backend_vulkan.c | 8 | ||||
-rw-r--r-- | src/renderer/backends/backend_vulkan.h | 2 | ||||
-rw-r--r-- | src/renderer/backends/metal/backend_metal.h | 42 | ||||
-rw-r--r-- | src/renderer/backends/opengl/backend_opengl.c | 204 | ||||
-rw-r--r-- | src/renderer/backends/opengl/backend_opengl.h | 9 | ||||
-rw-r--r-- | src/renderer/backends/opengl/opengl_helpers.h | 43 | ||||
-rw-r--r-- | src/renderer/ral.c | 7 | ||||
-rw-r--r-- | src/renderer/ral.h | 9 | ||||
-rw-r--r-- | src/renderer/ral_types.h | 6 | ||||
-rw-r--r-- | src/renderer/render_types.h | 1 | ||||
-rw-r--r-- | 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 <assert.h> +#define GLFW_INCLUDE_VULKAN #include <glfw3.h> + +#include <assert.h> #include <stddef.h> #include <stdint.h> #include <stdlib.h> @@ -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 <vulkan/vk_platform.h> #include <vulkan/vulkan.h> #include <vulkan/vulkan_core.h> -#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 <Foundation/Foundation.h> #import <Metal/Metal.h> #import <MetalKit/MetalKit.h> #import <QuartzCore/CAMetalLayer.h> -#import <Foundation/Foundation.h> #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<MTLDevice> 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<MTLRenderPipelineState> 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<MTLCommandBuffer> cmd_buffer; id<MTLRenderCommandEncoder> 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<MTLBuffer> 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 <assert.h> #include <stdlib.h> #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 <glad/glad.h> #include <glfw3.h> #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) @@ -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") |