diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/core.c | 8 | ||||
-rw-r--r-- | src/maths/maths.h | 2 | ||||
-rw-r--r-- | src/new_render/render.c | 30 | ||||
-rw-r--r-- | src/new_render/render.h | 3 | ||||
-rw-r--r-- | src/new_render/render_scene.h | 2 | ||||
-rw-r--r-- | src/new_render/shadows.c | 5 | ||||
-rw-r--r-- | src/new_render/shadows.h | 2 | ||||
-rw-r--r-- | src/platform/file.c | 2 | ||||
-rw-r--r-- | src/ral/backends/opengl/backend_opengl.c | 505 | ||||
-rw-r--r-- | src/ral/backends/opengl/backend_opengl.h | 7 | ||||
-rw-r--r-- | src/ral/backends/opengl/opengl_helpers.h (renamed from src/render/backends/opengl/opengl_helpers.h) | 70 | ||||
-rw-r--r-- | src/ral/ral_common.h | 12 | ||||
-rw-r--r-- | src/ral/ral_impl.h | 8 | ||||
-rw-r--r-- | src/ral/ral_types.h | 9 | ||||
-rw-r--r-- | src/std/str.c | 88 | ||||
-rw-r--r-- | src/std/str.h | 2 |
16 files changed, 456 insertions, 299 deletions
diff --git a/src/core/core.c b/src/core/core.c index 6ccd0d0..de67b56 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -22,6 +22,8 @@ inline Core* GetCore() { return &g_core; } void Core_Bringup() { INFO("Initiate Core bringup"); + memset(&g_core, 0, sizeof(Core)); + RendererConfig conf = { .window_name = { "Celeritas Engine Core" }, .scr_width = SCR_WIDTH, .scr_height = SCR_HEIGHT, @@ -29,7 +31,7 @@ void Core_Bringup() { g_core.renderer = malloc(Renderer_GetMemReqs()); // initialise all subsystems - if (!Renderer_Init(conf, g_core.renderer)) { + if (!Renderer_Init(conf, g_core.renderer, &g_core.window)) { // FATAL("Failed to start renderer"); ERROR_EXIT("Failed to start renderer\n"); } @@ -50,8 +52,6 @@ void Core_Bringup() { // scene_init(&g_core.default_scene); } -#include <glfw3.h> - void Core_Shutdown() { Input_Shutdown(&g_core.input); Renderer_Shutdown(g_core.renderer); @@ -63,7 +63,7 @@ bool ShouldExit() { } void Frame_Begin() { - glfwPollEvents(); + Input_Update(&g_core.input); Render_FrameBegin(g_core.renderer); } void Frame_Draw() {} diff --git a/src/maths/maths.h b/src/maths/maths.h index 76790ea..930ee0a 100644 --- a/src/maths/maths.h +++ b/src/maths/maths.h @@ -21,7 +21,7 @@ // --- Vector Implementations // Dimension 3 -static inline Vec3 vec3_create(f32 x, f32 y, f32 z) { return (Vec3){ x, y, z }; } +PUB static inline Vec3 vec3_create(f32 x, f32 y, f32 z) { return (Vec3){ x, y, z }; } #define vec3(x, y, z) ((Vec3){ x, y, z }) static inline Vec3 vec3_add(Vec3 a, Vec3 b) { return (Vec3){ a.x + b.x, a.y + b.y, a.z + b.z }; } static inline Vec3 vec3_sub(Vec3 a, Vec3 b) { return (Vec3){ a.x - b.x, a.y - b.y, a.z - b.z }; } diff --git a/src/new_render/render.c b/src/new_render/render.c index 21046ea..1fef610 100644 --- a/src/new_render/render.c +++ b/src/new_render/render.c @@ -35,7 +35,9 @@ struct Renderer { ResourcePools* resource_pools; }; -bool Renderer_Init(RendererConfig config, Renderer* ren) { +Renderer* get_renderer() { return g_core.renderer; } + +bool Renderer_Init(RendererConfig config, Renderer* ren, GLFWwindow** out_window) { INFO("Renderer init"); // init resource pools @@ -66,6 +68,7 @@ bool Renderer_Init(RendererConfig config, Renderer* ren) { return false; } ren->window = window; + *out_window = window; glfwMakeContextCurrent(ren->window); @@ -81,16 +84,17 @@ bool Renderer_Init(RendererConfig config, Renderer* ren) { Camera default_cam = Camera_Create(vec3(0.0, 2.0, 4.0), vec3_normalise(vec3(0.0, -2.0, -4.0)), VEC3_Y, 45.0); SetCamera(default_cam); - PointLight default_light = { /* TODO */ }; - SetPointLight(default_light); + DirectionalLight default_light = { /* TODO */ }; + SetMainLight(default_light); // create our renderpasses - Shadow_Init(ren->shadows); + ren->shadows = malloc(sizeof(Shadow_Storage)); + Shadow_Init(ren->shadows, u32x2(512, 512)); return true; } -void Renderer_Shutdown(Renderer* ren) {} +void Renderer_Shutdown(Renderer* ren) { free(ren->shadows); } size_t Renderer_GetMemReqs() { return sizeof(Renderer); } void Render_FrameBegin(Renderer* ren) { @@ -107,9 +111,11 @@ void Render_FrameEnd(Renderer* ren) { } GPU_CmdEncoder* enc = GPU_GetDefaultEncoder(); + + GPU_Backend_EndFrame(); } void Render_RenderEntities(RenderEnt* entities, size_t entity_count) { - Renderer* ren = Core_GetRenderer(&g_core); + Renderer* ren = get_renderer(); RenderScene scene = ren->scene; // -- Shadows @@ -144,3 +150,15 @@ Mesh Mesh_Create(Geometry* geometry, bool free_on_upload) { } return m; } + +void Geometry_Destroy(Geometry* geometry) { + if (geometry->indices) { + u32_darray_free(geometry->indices); + } + if (geometry->vertices) { + Vertex_darray_free(geometry->vertices); + } +} + +void SetCamera(Camera camera) { g_core.renderer->scene.camera = camera; } +void SetMainLight(DirectionalLight light) { g_core.renderer->scene.sun = light; }
\ No newline at end of file diff --git a/src/new_render/render.h b/src/new_render/render.h index 6e9f380..fa05fec 100644 --- a/src/new_render/render.h +++ b/src/new_render/render.h @@ -9,6 +9,7 @@ #include "render_types.h" typedef struct Renderer Renderer; +typedef struct GLFWwindow GLFWwindow; typedef struct RendererConfig { char window_name[256]; u32 scr_width, scr_height; @@ -22,7 +23,7 @@ typedef struct RenderCtx { // --- Lifecycle -PUB bool Renderer_Init(RendererConfig config, Renderer* renderer); +PUB bool Renderer_Init(RendererConfig config, Renderer* renderer, GLFWwindow** out_window); PUB void Renderer_Shutdown(Renderer* renderer); PUB size_t Renderer_GetMemReqs(); diff --git a/src/new_render/render_scene.h b/src/new_render/render_scene.h index 791e862..1e4660a 100644 --- a/src/new_render/render_scene.h +++ b/src/new_render/render_scene.h @@ -17,4 +17,4 @@ typedef struct RenderScene { // --- Public APIs PUB void SetCamera(Camera camera); -PUB void SetPointLight(PointLight light); +PUB void SetMainLight(DirectionalLight light); diff --git a/src/new_render/shadows.c b/src/new_render/shadows.c index df836b4..612fd34 100644 --- a/src/new_render/shadows.c +++ b/src/new_render/shadows.c @@ -1,6 +1,7 @@ -#include <string.h> #include "shadows.h" +#include <string.h> #include "core.h" +#include "file.h" #include "log.h" #include "maths.h" #include "ral_common.h" @@ -28,7 +29,7 @@ ShaderDataLayout ShadowUniforms_GetLayout(void* data) { }; if (has_data) { - b1.data.bytes.data = data; + b1.data.bytes.data = data; } return (ShaderDataLayout){ .binding_count = 1, .bindings = { b1 } }; diff --git a/src/new_render/shadows.h b/src/new_render/shadows.h index 81711de..4dc20e2 100644 --- a/src/new_render/shadows.h +++ b/src/new_render/shadows.h @@ -22,7 +22,7 @@ typedef struct Camera Camera; typedef struct Mat4 Mat4; // --- Public API -PUB void Shadow_Init(Shadow_Storage* storage); +PUB void Shadow_Init(Shadow_Storage* storage, u32x2 shadowmap_extents); /** @brief Run shadow map generation for given entities, and store in a texture. * @note Uses active directional light for now */ diff --git a/src/platform/file.c b/src/platform/file.c index 33194d7..ea69e20 100644 --- a/src/platform/file.c +++ b/src/platform/file.c @@ -51,7 +51,7 @@ str8_opt str8_from_file(arena *a, Str8 path) { rewind(f); u8 *raw = arena_alloc(a, fsize + 1); - Str8 contents = str8_create(raw, fsize); + Str8 contents = Str8_create(raw, fsize); contents.buf[contents.len] = '\0'; fread(raw, fsize, 1, f); diff --git a/src/ral/backends/opengl/backend_opengl.c b/src/ral/backends/opengl/backend_opengl.c index 2c7c411..cbfd855 100644 --- a/src/ral/backends/opengl/backend_opengl.c +++ b/src/ral/backends/opengl/backend_opengl.c @@ -1,7 +1,9 @@ -#include <assert.h> #include "backend_opengl.h" +#if defined(CEL_REND_BACKEND_OPENGL) +#include <assert.h> #include "log.h" #include "mem.h" +#include "opengl_helpers.h" #include "ral_common.h" #include "ral_impl.h" #include "ral_types.h" @@ -10,42 +12,43 @@ #include <glfw3.h> typedef struct OpenglCtx { - GLFWwindow* window; - arena pool_arena; - GPU_CmdBuffer main_cmd_buffer; - GPU_BackendPools gpu_pools; - ResourcePools* resource_pools; + GLFWwindow* window; + arena pool_arena; + GPU_CmdEncoder main_encoder; + GPU_BackendPools gpu_pools; + ResourcePools* resource_pools; } OpenglCtx; static OpenglCtx context; -bool GPU_Backend_Init(const char* window_name, struct GLFWwindow *window, struct ResourcePools* res_pools) { - INFO("loading OpenGL backend"); +bool GPU_Backend_Init(const char* window_name, struct GLFWwindow* window, + struct ResourcePools* res_pools) { + INFO("loading OpenGL backend"); - memset(&context, 0, sizeof(context)); - context.window = window; + memset(&context, 0, sizeof(context)); + context.window = window; - size_t pool_buffer_size = 1024 * 1024; - context.pool_arena = arena_create(malloc(pool_buffer_size), pool_buffer_size); + size_t pool_buffer_size = 1024 * 1024; + context.pool_arena = arena_create(malloc(pool_buffer_size), pool_buffer_size); - BackendPools_Init(&context.pool_arena, &context.gpu_pools); - context.resource_pools = res_pools; + BackendPools_Init(&context.pool_arena, &context.gpu_pools); + context.resource_pools = res_pools; - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + 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; - } + // glad: load all opengl function pointers + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { + ERROR("Failed to initialise GLAD \n"); + return false; + } - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); - return true; + return true; } // All of these are no-ops in OpenGL @@ -57,108 +60,107 @@ void GPU_Swapchain_Destroy(GPU_Swapchain* swapchain) {} void GPU_CmdEncoder_Destroy(GPU_CmdEncoder* encoder) {} void GPU_CmdEncoder_BeginRender(GPU_CmdEncoder* encoder, GPU_Renderpass* renderpass) {} void GPU_CmdEncoder_EndRender(GPU_CmdEncoder* encoder) {} -GPU_CmdEncoder* GPU_GetDefaultEncoder() { - return context. -} +GPU_CmdEncoder* GPU_GetDefaultEncoder() { return &context.main_encoder; } void GPU_QueueSubmit(GPU_CmdBuffer* cmd_buffer) {} GPU_Renderpass* GPU_Renderpass_Create(GPU_RenderpassDesc description) { - // allocate new pass - GPU_Renderpass* renderpass = Renderpass_pool_alloc(&context.gpu_pools.renderpasses, NULL); - renderpass->description = description; - - if (!description.default_framebuffer) { - // If we're not using the default framebuffer we need to generate a new one - GLuint gl_fbo_id; - glGenFramebuffers(1, &gl_fbo_id); - renderpass->fbo = gl_fbo_id; - } else { - renderpass->fbo = OPENGL_DEFAULT_FRAMEBUFFER; - assert(!description.has_color_target); - assert(!description.has_depth_stencil); - } - glBindFramebuffer(GL_FRAMEBUFFER, renderpass->fbo); - - if (description.has_color_target && !description.default_framebuffer) { - GPU_Texture* colour_attachment = TEXTURE_GET(description.color_target); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - colour_attachment->id, 0); - } - if (description.has_depth_stencil && !description.default_framebuffer) { - GPU_Texture* depth_attachment = TEXTURE_GET(description.depth_stencil); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_attachment->id, - 0); - } - - if (description.has_depth_stencil && !description.has_color_target) { - glDrawBuffer(GL_NONE); - glReadBuffer(GL_NONE); - } - - glBindFramebuffer(GL_FRAMEBUFFER, 0); // reset to default framebuffer - - return renderpass; + // allocate new pass + GPU_Renderpass* renderpass = Renderpass_pool_alloc(&context.gpu_pools.renderpasses, NULL); + renderpass->description = description; + + if (!description.default_framebuffer) { + // If we're not using the default framebuffer we need to generate a new one + GLuint gl_fbo_id; + glGenFramebuffers(1, &gl_fbo_id); + renderpass->fbo = gl_fbo_id; + } else { + renderpass->fbo = OPENGL_DEFAULT_FRAMEBUFFER; + assert(!description.has_color_target); + assert(!description.has_depth_stencil); + } + glBindFramebuffer(GL_FRAMEBUFFER, renderpass->fbo); + + if (description.has_color_target && !description.default_framebuffer) { + GPU_Texture* colour_attachment = TEXTURE_GET(description.color_target); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + colour_attachment->id, 0); + } + if (description.has_depth_stencil && !description.default_framebuffer) { + GPU_Texture* depth_attachment = TEXTURE_GET(description.depth_stencil); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_attachment->id, + 0); + } + + if (description.has_depth_stencil && !description.has_color_target) { + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); // reset to default framebuffer + + return renderpass; } void GPU_Renderpass_Destroy(GPU_Renderpass* pass) { glDeleteFramebuffers(1, &pass->fbo); } -GPU_Pipeline* GPU_GraphicsPipeline_Create(GraphicsPipelineDesc description, GPU_Renderpass* renderpass) { - GPU_Pipeline* pipeline = Pipeline_pool_alloc(&context.gpu_pools.pipelines, NULL); - - // Create shader program - u32 shader_id = shader_create_separate(description.vs.filepath.buf, description.fs.filepath.buf); - pipeline->shader_id = shader_id; - - // Vertex format - pipeline->vertex_desc = description.vertex_desc; - - // Allocate uniform buffers if needed - u32 ubo_count = 0; - // printf("data layouts %d\n", description.data_layouts_count); - for (u32 layout_i = 0; layout_i < description.data_layouts_count; layout_i++) { - ShaderDataLayout sdl = description.data_layouts[layout_i].get_layout(NULL); - TRACE("Got shader data layout %d's bindings! . found %d", layout_i, sdl.binding_count); - - for (u32 binding_j = 0; binding_j < sdl.binding_count; binding_j++) { - u32 binding_id = binding_j; - assert(binding_id < MAX_PIPELINE_UNIFORM_BUFFERS); - ShaderBinding binding = sdl.bindings[binding_j]; - // Do I want Buffer vs Bytes? - if (binding.kind == BINDING_BUFFER) { - static u32 s_binding_point = 0; - BufferHandle ubo_handle = - GPU_BufferCreate(binding.data.bytes.size, BUFFER_UNIFORM, BUFFER_FLAG_GPU, NULL); // no data right now - pipeline->uniform_bindings[ubo_count++] = ubo_handle; - GPU_Buffer* ubo_buf = BUFFER_GET(ubo_handle); - - i32 blockIndex = glGetUniformBlockIndex(pipeline->shader_id, binding.label); - printf("Block index for %s: %d", binding.label, blockIndex); - if (blockIndex < 0) { - WARN("Couldn't retrieve block index for uniform block '%s'", binding.label); - } else { - // DEBUG("Retrived block index %d for %s", blockIndex, binding.label); - } - u32 blocksize; - glGetActiveUniformBlockiv(pipeline->shader_id, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, - &blocksize); - printf("\t with size %d bytes\n", blocksize); - - glBindBufferBase(GL_UNIFORM_BUFFER, s_binding_point, ubo_buf->id.ubo); - if (blockIndex != GL_INVALID_INDEX) { - glUniformBlockBinding(pipeline->shader_id, blockIndex, s_binding_point); - } - ubo_buf->ubo_binding_point = s_binding_point++; - ubo_buf->name = binding.label; - assert(s_binding_point < GL_MAX_UNIFORM_BUFFER_BINDINGS); +GPU_Pipeline* GPU_GraphicsPipeline_Create(GraphicsPipelineDesc description, + GPU_Renderpass* renderpass) { + GPU_Pipeline* pipeline = Pipeline_pool_alloc(&context.gpu_pools.pipelines, NULL); + + // Create shader program + u32 shader_id = shader_create_separate(description.vs.filepath.buf, description.fs.filepath.buf); + pipeline->shader_id = shader_id; + + // Vertex format + pipeline->vertex_desc = description.vertex_desc; + + // Allocate uniform buffers if needed + u32 ubo_count = 0; + // printf("data layouts %d\n", description.data_layouts_count); + for (u32 layout_i = 0; layout_i < description.data_layouts_count; layout_i++) { + ShaderDataLayout sdl = description.data_layouts[layout_i].get_layout(NULL); + TRACE("Got shader data layout %d's bindings! . found %d", layout_i, sdl.binding_count); + + for (u32 binding_j = 0; binding_j < sdl.binding_count; binding_j++) { + u32 binding_id = binding_j; + assert(binding_id < MAX_PIPELINE_UNIFORM_BUFFERS); + ShaderBinding binding = sdl.bindings[binding_j]; + // Do I want Buffer vs Bytes? + if (binding.kind == BINDING_BUFFER) { + static u32 s_binding_point = 0; + BufferHandle ubo_handle = GPU_BufferCreate(binding.data.bytes.size, BUFFER_UNIFORM, + BUFFER_FLAG_GPU, NULL); // no data right now + pipeline->uniform_bindings[ubo_count++] = ubo_handle; + GPU_Buffer* ubo_buf = BUFFER_GET(ubo_handle); + + i32 blockIndex = glGetUniformBlockIndex(pipeline->shader_id, binding.label); + printf("Block index for %s: %d", binding.label, blockIndex); + if (blockIndex < 0) { + WARN("Couldn't retrieve block index for uniform block '%s'", binding.label); + } else { + // DEBUG("Retrived block index %d for %s", blockIndex, binding.label); } + u32 blocksize; + glGetActiveUniformBlockiv(pipeline->shader_id, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, + &blocksize); + printf("\t with size %d bytes\n", blocksize); + + glBindBufferBase(GL_UNIFORM_BUFFER, s_binding_point, ubo_buf->id.ubo); + if (blockIndex != GL_INVALID_INDEX) { + glUniformBlockBinding(pipeline->shader_id, blockIndex, s_binding_point); + } + ubo_buf->ubo_binding_point = s_binding_point++; + ubo_buf->name = binding.label; + assert(s_binding_point < GL_MAX_UNIFORM_BUFFER_BINDINGS); } } - pipeline->uniform_count = ubo_count; + } + pipeline->uniform_count = ubo_count; - pipeline->renderpass = description.renderpass; - pipeline->wireframe = description.wireframe; + pipeline->renderpass = renderpass; + pipeline->wireframe = description.wireframe; - return pipeline; + return pipeline; } void GraphicsPipeline_Destroy(GPU_Pipeline* pipeline) {} @@ -168,117 +170,190 @@ GPU_CmdEncoder GPU_CmdEncoder_Create() { return encoder; } +BufferHandle GPU_BufferCreate(u64 size, GPU_BufferType buf_type, GPU_BufferFlags flags, + const void* data) { + // "allocating" the cpu-side buffer struct + BufferHandle handle; + GPU_Buffer* buffer = Buffer_pool_alloc(&context.resource_pools, &handle); + buffer->size = size; + buffer->vao = 0; + + // Opengl buffer + GLuint gl_buffer_id; + glGenBuffers(1, &gl_buffer_id); + + GLenum gl_buf_type; + GLenum gl_buf_usage = GL_STATIC_DRAW; + + switch (buf_type) { + case BUFFER_UNIFORM: + DEBUG("Creating Uniform buffer"); + gl_buf_type = GL_UNIFORM_BUFFER; + /* gl_buf_usage = GL_DYNAMIC_DRAW; */ + buffer->id.ubo = gl_buffer_id; + break; + case BUFFER_DEFAULT: + case BUFFER_VERTEX: + DEBUG("Creating Vertex buffer"); + gl_buf_type = GL_ARRAY_BUFFER; + buffer->id.vbo = gl_buffer_id; + break; + case BUFFER_INDEX: + DEBUG("Creating Index buffer"); + gl_buf_type = GL_ELEMENT_ARRAY_BUFFER; + buffer->id.ibo = gl_buffer_id; + break; + default: + WARN("Unimplemented gpu_buffer_type provided %s", buffer_type_names[buf_type]); + break; + } + // bind buffer + glBindBuffer(gl_buf_type, gl_buffer_id); + + if (data) { + TRACE("Upload data (%d bytes) as part of buffer creation", size); + glBufferData(gl_buf_type, buffer->size, data, gl_buf_usage); + } else { + TRACE("Allocating but not uploading (%d bytes)", size); + glBufferData(gl_buf_type, buffer->size, NULL, gl_buf_usage); + } + + glBindBuffer(gl_buf_type, 0); + + return handle; +} -BufferHandle GPU_BufferCreate(u64 size, GPU_BufferType buf_type, GPU_BufferFlags flags, const void *data) { - // "allocating" the cpu-side buffer struct - BufferHandle handle; - GPU_Buffer* buffer = Buffer_pool_alloc(&context.resource_pools, &handle); - buffer->size = size; - buffer->vao = 0; - - // Opengl buffer - GLuint gl_buffer_id; - glGenBuffers(1, &gl_buffer_id); - - GLenum gl_buf_type; - GLenum gl_buf_usage = GL_STATIC_DRAW; - - switch (buf_type) { - case BUFFER_UNIFORM: - DEBUG("Creating Uniform buffer"); - gl_buf_type = GL_UNIFORM_BUFFER; - /* gl_buf_usage = GL_DYNAMIC_DRAW; */ - buffer->id.ubo = gl_buffer_id; - break; - case BUFFER_DEFAULT: - case BUFFER_VERTEX: - DEBUG("Creating Vertex buffer"); - gl_buf_type = GL_ARRAY_BUFFER; - buffer->id.vbo = gl_buffer_id; - break; - case BUFFER_INDEX: - DEBUG("Creating Index buffer"); - gl_buf_type = GL_ELEMENT_ARRAY_BUFFER; - buffer->id.ibo = gl_buffer_id; - break; - default: - WARN("Unimplemented gpu_buffer_type provided %s", buffer_type_names[buf_type]); - break; - } - // bind buffer - glBindBuffer(gl_buf_type, gl_buffer_id); - - if (data) { - TRACE("Upload data (%d bytes) as part of buffer creation", size); - glBufferData(gl_buf_type, buffer->size, data, gl_buf_usage); - } else { - TRACE("Allocating but not uploading (%d bytes)", size); - glBufferData(gl_buf_type, buffer->size, NULL, gl_buf_usage); - } +TextureHandle GPU_TextureCreate(TextureDesc desc, bool create_view, const void* data) { + // "allocating" the cpu-side struct + TextureHandle handle; + GPU_Texture* texture = Texture_pool_alloc(&context.resource_pools->textures, &handle); + DEBUG("Allocated texture with handle %d", handle.raw); + + GLuint gl_texture_id; + glGenTextures(1, &gl_texture_id); + texture->id = gl_texture_id; + + glBindTexture(GL_TEXTURE_2D, gl_texture_id); + + GLint internal_format = desc.format == TEXTURE_FORMAT_DEPTH_DEFAULT ? GL_DEPTH_COMPONENT : GL_RGB; + GLenum format = desc.format == TEXTURE_FORMAT_DEPTH_DEFAULT ? GL_DEPTH_COMPONENT : GL_RGBA; + GLenum data_type = desc.format == TEXTURE_FORMAT_DEPTH_DEFAULT ? GL_FLOAT : GL_UNSIGNED_BYTE; + + if (desc.format == TEXTURE_FORMAT_DEPTH_DEFAULT) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + } else { + // set the texture wrapping parameters + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + // set texture filtering parameters + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + + if (data) { + glTexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.extents.x, desc.extents.y, 0, format, + data_type, data); + glGenerateMipmap(GL_TEXTURE_2D); + } else { + WARN("No image data provided"); + glTexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.extents.x, desc.extents.y, 0, format, + data_type, NULL); + } + + glBindTexture(GL_TEXTURE_2D, 0); + + return handle; +} - glBindBuffer(gl_buf_type, 0); +void GPU_TextureDestroy(TextureHandle handle) { glDeleteTextures(1, &handle.raw); } - return handle; +// TODO: void GPU_TextureUpload(TextureHandle handle, size_t n_bytes, const void* data) + +void GPU_EncodeBindPipeline(GPU_CmdEncoder* encoder, GPU_Pipeline* pipeline) { + encoder->pipeline = pipeline; + + // In OpenGL binding a pipeline is more or less equivalent to just setting the shader + glUseProgram(pipeline->shader_id); } -TextureHandle GPU_TextureCreate(TextureDesc desc, bool create_view, const void *data) { - // "allocating" the cpu-side struct - TextureHandle handle; - GPU_Texture* texture = Texture_pool_alloc(&context.resource_pools->textures, &handle); - DEBUG("Allocated texture with handle %d", handle.raw); - - GLuint gl_texture_id; - glGenTextures(1, &gl_texture_id); - texture->id = gl_texture_id; - - glBindTexture(GL_TEXTURE_2D, gl_texture_id); - - GLint internal_format = - desc.format == TEXTURE_FORMAT_DEPTH_DEFAULT ? GL_DEPTH_COMPONENT : GL_RGB; - GLenum format = desc.format == TEXTURE_FORMAT_DEPTH_DEFAULT ? GL_DEPTH_COMPONENT : GL_RGBA; - GLenum data_type = desc.format == TEXTURE_FORMAT_DEPTH_DEFAULT ? GL_FLOAT : GL_UNSIGNED_BYTE; - - if (desc.format == TEXTURE_FORMAT_DEPTH_DEFAULT) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - } else { - // set the texture wrapping parameters - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - // set texture filtering parameters - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } +PUB void GPU_EncodeBindShaderData(GPU_CmdEncoder* encoder, u32 group, ShaderData data) { + ShaderDataLayout sdl = data.get_layout(data.data); + + for (u32 i = 0; i < sdl.binding_count; i++) { + ShaderBinding binding = sdl.bindings[i]; + /* print_shader_binding(binding); */ + + if (binding.kind == BINDING_BYTES) { + BufferHandle b; + GPU_Buffer* ubo_buf; + bool found = false; + for (u32 i = 0; i < encoder->pipeline->uniform_count; i++) { + b = encoder->pipeline->uniform_bindings[i]; + ubo_buf = BUFFER_GET(b); + assert(ubo_buf->name != NULL); + if (strcmp(ubo_buf->name, binding.label) == 0) { + found = true; + break; + } + } + if (!found) { + ERROR("Couldnt find uniform buffer object!!"); + } - if (data) { - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.extents.x, desc.extents.y, 0, format, - data_type, data); - glGenerateMipmap(GL_TEXTURE_2D); - } else { - WARN("No image data provided"); - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.extents.x, desc.extents.y, 0, format, - data_type, NULL); - } + i32 blockIndex = glGetUniformBlockIndex(encoder->pipeline->shader_id, binding.label); + if (blockIndex < 0) { + WARN("Couldn't retrieve block index for uniform block '%s'", binding.label); + } else { + // DEBUG("Retrived block index %d for %s", blockIndex, binding.label); + } - glBindTexture(GL_TEXTURE_2D, 0); + glBindBuffer(GL_UNIFORM_BUFFER, ubo_buf->id.ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, ubo_buf->size, binding.data.bytes.data); - return handle; + } else if (binding.kind == BINDING_TEXTURE) { + GPU_Texture* tex = TEXTURE_GET(binding.data.texture.handle); + GLint tex_slot = glGetUniformLocation(encoder->pipeline->shader_id, binding.label); + // printf("%d slot \n", tex_slot); + if (tex_slot == GL_INVALID_VALUE || tex_slot < 0) { + WARN("Invalid binding label for texture %s - couldn't fetch texture slot uniform", + binding.label); + } + glUniform1i(tex_slot, i); + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, tex->id); + } + } } -void GPU_TextureDestroy(TextureHandle handle) { - glDeleteTextures(1, &handle.raw); -} +void GPU_EncodeSetDefaults(GPU_CmdEncoder* encoder) {} -// TODO: void GPU_TextureUpload(TextureHandle handle, size_t n_bytes, const void* data) +void GPU_EncodeSetVertexBuffer(GPU_CmdEncoder* encoder, BufferHandle buf) { + GPU_Buffer* buffer = BUFFER_GET(buf); + if (buffer->vao == 0) { // if no VAO for this vertex buffer, create it + INFO("Setting up VAO"); + buffer->vao = opengl_bindcreate_vao(buffer, encoder->pipeline->vertex_desc); + } + glBindVertexArray(buffer->vao); +} +void GPU_EncodeSetIndexBuffer(GPU_CmdEncoder* encoder, BufferHandle buf) { + GPU_Buffer* buffer = BUFFER_GET(buf); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->id.ibo); +} +void GPU_EncodeDraw(GPU_CmdEncoder* encoder, u64 count) { glDrawArrays(GL_TRIANGLES, 0, count); } +void GPU_EncodeDrawIndexed(GPU_CmdEncoder* encoder, u64 index_count) { + glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_INT, 0); +} bool GPU_Backend_BeginFrame() { - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + return true; } -void GPU_Backend_EndFrame() { - glfwSwapBuffers(context.window); -} +void GPU_Backend_EndFrame() { glfwSwapBuffers(context.window); } + +#endif
\ No newline at end of file diff --git a/src/ral/backends/opengl/backend_opengl.h b/src/ral/backends/opengl/backend_opengl.h index 4fbb4bb..f8e76b8 100644 --- a/src/ral/backends/opengl/backend_opengl.h +++ b/src/ral/backends/opengl/backend_opengl.h @@ -1,11 +1,10 @@ #pragma once +#include "defines.h" -#include "ral_impl.h" -#ifdef CEL_REND_BACKEND_OPENGL +#if defined(CEL_REND_BACKEND_OPENGL) -#include "defines.h" #include "maths_types.h" -#include "ral.h" +#include "ral_impl.h" #include "ral_types.h" #define MAX_PIPELINE_UNIFORM_BUFFERS 32 diff --git a/src/render/backends/opengl/opengl_helpers.h b/src/ral/backends/opengl/opengl_helpers.h index 41018cb..f40bbca 100644 --- a/src/render/backends/opengl/opengl_helpers.h +++ b/src/ral/backends/opengl/opengl_helpers.h @@ -1,19 +1,23 @@ -#if defined(CEL_REND_BACKEND_OPENGL) #pragma once +#include "defines.h" +#include "ral_common.h" +#include "ral_impl.h" +#if defined(CEL_REND_BACKEND_OPENGL) #include "backend_opengl.h" #include "log.h" -#include "ral.h" +#include "file.h" #include "ral_types.h" #include <glad/glad.h> #include <glfw3.h> #include "ral_types.h" + typedef struct opengl_vertex_attr { u32 count; GLenum data_type; } opengl_vertex_attr; -static opengl_vertex_attr format_from_vertex_attr(vertex_attrib_type attr) { +static opengl_vertex_attr format_from_vertex_attr(VertexAttribType attr) { switch (attr) { case ATTR_F32: return (opengl_vertex_attr){ .count = 1, .data_type = GL_FLOAT }; @@ -42,7 +46,7 @@ static opengl_vertex_attr format_from_vertex_attr(vertex_attrib_type attr) { } } -static u32 opengl_bindcreate_vao(gpu_buffer* buf, vertex_description desc) { +static u32 opengl_bindcreate_vao(GPU_Buffer* buf, VertexDescription desc) { DEBUG("Vertex format name %s", desc.debug_label); // 1. Bind the buffer glBindBuffer(GL_ARRAY_BUFFER, buf->id.vbo); @@ -55,15 +59,15 @@ 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.use_full_vertex_size ? sizeof(vertex) : 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); 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); + size_t this_offset = VertexAttribSize(desc.attributes[i]); + printf("offset total %lld this attr %zu\n", offset, this_offset); offset += this_offset; } glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -71,4 +75,56 @@ static u32 opengl_bindcreate_vao(gpu_buffer* buf, vertex_description desc) { return vao; } +static u32 shader_create_separate(const char* vert_shader, const char* frag_shader) { + INFO("Load shaders at %s and %s", vert_shader, frag_shader); + int success; + char info_log[512]; + + u32 vertex = glCreateShader(GL_VERTEX_SHADER); + const char* vertex_shader_src = string_from_file(vert_shader); + if (vertex_shader_src == NULL) { + ERROR("EXIT: couldnt load shader"); + exit(-1); + } + glShaderSource(vertex, 1, &vertex_shader_src, NULL); + glCompileShader(vertex); + glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); + if (!success) { + glGetShaderInfoLog(vertex, 512, NULL, info_log); + printf("%s\n", info_log); + ERROR("EXIT: vertex shader compilation failed"); + exit(-1); + } + + // fragment shader + u32 fragment = glCreateShader(GL_FRAGMENT_SHADER); + const char* fragment_shader_src = string_from_file(frag_shader); + if (fragment_shader_src == NULL) { + ERROR("EXIT: couldnt load shader"); + exit(-1); + } + glShaderSource(fragment, 1, &fragment_shader_src, NULL); + glCompileShader(fragment); + glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); + if (!success) { + glGetShaderInfoLog(fragment, 512, NULL, info_log); + printf("%s\n", info_log); + ERROR("EXIT: fragment shader compilation failed"); + exit(-1); + } + + u32 shader_prog; + shader_prog = glCreateProgram(); + + glAttachShader(shader_prog, vertex); + glAttachShader(shader_prog, fragment); + glLinkProgram(shader_prog); + glDeleteShader(vertex); + glDeleteShader(fragment); + free((char*)vertex_shader_src); + free((char*)fragment_shader_src); + + return shader_prog; +} + #endif diff --git a/src/ral/ral_common.h b/src/ral/ral_common.h index 0f7c1b7..6a373ee 100644 --- a/src/ral/ral_common.h +++ b/src/ral/ral_common.h @@ -6,7 +6,13 @@ #include "buf.h" #include "mem.h" #include "ral_types.h" -#include "ral_impl.h" +// #include "ral_impl.h" + +// Concrete implementation +#if defined(CEL_REND_BACKEND_OPENGL) +#include "backend_opengl.h" +#endif + TYPED_POOL(GPU_Buffer, Buffer); TYPED_POOL(GPU_Texture, Texture); @@ -15,8 +21,8 @@ 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)) +#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_BackendPools { diff --git a/src/ral/ral_impl.h b/src/ral/ral_impl.h index 3c3eaa5..7cc9459 100644 --- a/src/ral/ral_impl.h +++ b/src/ral/ral_impl.h @@ -4,7 +4,6 @@ #pragma once #include "buf.h" #include "defines.h" -#include "ral_common.h" #include "ral_types.h" struct GLFWwindow; @@ -77,9 +76,4 @@ PUB void GPU_EncodeDrawIndexed(GPU_CmdEncoder* encoder, u64 index_count); // --- Frame cycle PUB bool GPU_Backend_BeginFrame(); -PUB void GPU_Backend_EndFrame(); - -// Concrete implementation -#if defined(CEL_REND_BACKEND_OPENGL) -#include "backend_opengl.h" -#endif +PUB void GPU_Backend_EndFrame();
\ No newline at end of file diff --git a/src/ral/ral_types.h b/src/ral/ral_types.h index 4470700..ffcc2cd 100644 --- a/src/ral/ral_types.h +++ b/src/ral/ral_types.h @@ -2,6 +2,7 @@ #include "defines.h" #include "darray.h" #include "maths_types.h" +#include "str.h" // --- Max size constants #define MAX_SHADER_DATA_LAYOUTS 8 @@ -149,7 +150,13 @@ typedef enum ShaderVisibility { VISIBILITY_COMPUTE = 1 << 2, } ShaderVisibility ; -typedef struct ShaderDesc {} ShaderDesc; +typedef struct ShaderDesc { + const char* debug_name; + Str8 filepath; // Where it came from + Str8 code; // Either GLSL or SPIRV bytecode + bool is_spirv; + bool is_combined_vert_frag; // Contains both vertex and fragment stages +} ShaderDesc; typedef enum ShaderBindingKind { BINDING_BYTES, diff --git a/src/std/str.c b/src/std/str.c index e15c38f..2aac15f 100644 --- a/src/std/str.c +++ b/src/std/str.c @@ -3,62 +3,62 @@ #include <string.h> #include "mem.h" -// str8 str8_create(u8* buf, size_t len) { return (str8){ .buf = buf, .len = len }; } +Str8 Str8_create(u8* buf, size_t len) { return (Str8){ .buf = buf, .len = len }; } -// str8 str8_cstr_view(char* string) { return str8_create((u8*)string, strlen(string)); } +Str8 Str8_cstr_view(char* string) { return Str8_create((u8*)string, strlen(string)); } -// bool str8_equals(str8 a, str8 b) { -// if (a.len != b.len) { -// return false; -// } +bool Str8_equals(Str8 a, Str8 b) { + if (a.len != b.len) { + return false; + } -// for (size_t i = 0; i < a.len; i++) { -// if (a.buf[i] != b.buf[i]) { -// return false; -// } -// } -// return true; -// } + for (size_t i = 0; i < a.len; i++) { + if (a.buf[i] != b.buf[i]) { + return false; + } + } + return true; +} -// char* str8_to_cstr(arena* a, str8 s) { -// bool is_null_terminated = s.buf[s.len - 1] == 0; -// size_t n_bytes = is_null_terminated ? s.len : s.len + 1; +char* Str8_to_cstr(arena* a, Str8 s) { + bool is_null_terminated = s.buf[s.len - 1] == 0; + size_t n_bytes = is_null_terminated ? s.len : s.len + 1; -// u8* dest = arena_alloc(a, n_bytes); + u8* dest = arena_alloc(a, n_bytes); -// memcpy(dest, s.buf, s.len); -// if (is_null_terminated) { -// dest[s.len] = '\0'; -// } -// return (char*)dest; -// } + memcpy(dest, s.buf, s.len); + if (is_null_terminated) { + dest[s.len] = '\0'; + } + return (char*)dest; +} -// str8 str8_concat(arena* a, str8 left, str8 right) { -// size_t n_bytes = left.len + right.len + 1; +Str8 Str8_concat(arena* a, Str8 left, Str8 right) { + size_t n_bytes = left.len + right.len + 1; -// u8* dest = arena_alloc(a, n_bytes); -// memcpy(dest, left.buf, left.len); -// memcpy(dest + right.len, right.buf, right.len); + u8* dest = arena_alloc(a, n_bytes); + memcpy(dest, left.buf, left.len); + memcpy(dest + right.len, right.buf, right.len); -// dest[n_bytes - 1] = '\0'; + dest[n_bytes - 1] = '\0'; -// return str8_create(dest, n_bytes); -// } + return Str8_create(dest, n_bytes); +} -// str8 str8_substr(str8 s, u64 min, u64 max) { -// assert(min >= 0); -// assert(min < s.len); -// assert(max >= 0); -// assert(max <= s.len); -// uint8_t* start = s.buf + (ptrdiff_t)min; -// size_t new_len = max - min; -// return (str8){ .buf = start, .len = new_len }; -// } +Str8 Str8_substr(Str8 s, u64 min, u64 max) { + assert(min >= 0); + assert(min < s.len); + assert(max >= 0); + assert(max <= s.len); + uint8_t* start = s.buf + (ptrdiff_t)min; + size_t new_len = max - min; + return (Str8){ .buf = start, .len = new_len }; +} -// str8 str8_take(str8 s, u64 first_n) { return str8_substr(s, 0, first_n); } +Str8 Str8_take(Str8 s, u64 first_n) { return Str8_substr(s, 0, first_n); } -// str8 str8_drop(str8 s, u64 last_n) { return str8_substr(s, s.len - last_n, s.len); } +Str8 Str8_drop(Str8 s, u64 last_n) { return Str8_substr(s, s.len - last_n, s.len); } -// str8 str8_skip(str8 s, u64 n) { return str8_substr(s, n, s.len); } +Str8 Str8_skip(Str8 s, u64 n) { return Str8_substr(s, n, s.len); } -// str8 str8_chop(str8 s, u64 n) { return str8_substr(s, 0, s.len - n); } +Str8 Str8_chop(Str8 s, u64 n) { return Str8_substr(s, 0, s.len - n); } diff --git a/src/std/str.h b/src/std/str.h index e9c4098..9e712e6 100644 --- a/src/std/str.h +++ b/src/std/str.h @@ -31,7 +31,7 @@ typedef struct { #define str8(s) \ (Str8) { (u8*)s, ((sizeof(s) / sizeof(*(s)) - 1)) } -Str8 str8_create(u8* buf, size_t len); +Str8 Str8_create(u8* buf, size_t len); /** @brief Return a null-terminated C string cloned onto an arena */ char* Str8_to_cstr(arena* a, Str8 s); |