summaryrefslogtreecommitdiff
path: root/src/ral
diff options
context:
space:
mode:
authoromnisci3nce <omniscient.oce@gmail.com>2024-07-14 21:47:25 +1000
committeromnisci3nce <omniscient.oce@gmail.com>2024-07-14 21:47:25 +1000
commit529a603128d5e9dc4701322f44961f165e2183e1 (patch)
tree3e5d65ac503b971412ae35bfc5fb67a438a3c364 /src/ral
parent5b001d39d42314085164724d3a417fb8ebd54f98 (diff)
generate api docs python
Diffstat (limited to 'src/ral')
-rw-r--r--src/ral/backends/opengl/backend_opengl.c284
-rw-r--r--src/ral/backends/opengl/backend_opengl.h6
-rw-r--r--src/ral/ral_common.c46
-rw-r--r--src/ral/ral_common.h20
-rw-r--r--src/ral/ral_impl.h56
-rw-r--r--src/ral/ral_types.h5
6 files changed, 395 insertions, 22 deletions
diff --git a/src/ral/backends/opengl/backend_opengl.c b/src/ral/backends/opengl/backend_opengl.c
new file mode 100644
index 0000000..2c7c411
--- /dev/null
+++ b/src/ral/backends/opengl/backend_opengl.c
@@ -0,0 +1,284 @@
+#include <assert.h>
+#include "backend_opengl.h"
+#include "log.h"
+#include "mem.h"
+#include "ral_common.h"
+#include "ral_impl.h"
+#include "ral_types.h"
+
+#include <glad/glad.h>
+#include <glfw3.h>
+
+typedef struct OpenglCtx {
+ GLFWwindow* window;
+ arena pool_arena;
+ GPU_CmdBuffer main_cmd_buffer;
+ GPU_BackendPools gpu_pools;
+ ResourcePools* resource_pools;
+} OpenglCtx;
+
+static OpenglCtx context;
+
+bool GPU_Backend_Init(const char* window_name, struct GLFWwindow *window, struct ResourcePools* res_pools) {
+ INFO("loading OpenGL backend");
+
+ memset(&context, 0, sizeof(context));
+ context.window = window;
+
+ size_t pool_buffer_size = 1024 * 1024;
+ context.pool_arena = arena_create(malloc(pool_buffer_size), pool_buffer_size);
+
+ BackendPools_Init(&context.pool_arena, &context.gpu_pools);
+ context.resource_pools = res_pools;
+
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
+
+ // glad: load all opengl function pointers
+ if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
+ ERROR("Failed to initialise GLAD \n");
+ return false;
+ }
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+
+ return true;
+}
+
+// All of these are no-ops in OpenGL
+void GPU_Backend_Shutdown() {}
+bool GPU_Device_Create(GPU_Device* out_device) { return true; }
+void GPU_Device_Destroy(GPU_Device* device) {}
+bool GPU_Swapchain_Create(GPU_Swapchain* out_swapchain) { return true; }
+void GPU_Swapchain_Destroy(GPU_Swapchain* swapchain) {}
+void GPU_CmdEncoder_Destroy(GPU_CmdEncoder* encoder) {}
+void GPU_CmdEncoder_BeginRender(GPU_CmdEncoder* encoder, GPU_Renderpass* renderpass) {}
+void GPU_CmdEncoder_EndRender(GPU_CmdEncoder* encoder) {}
+GPU_CmdEncoder* GPU_GetDefaultEncoder() {
+ return context.
+}
+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;
+}
+
+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);
+ }
+ }
+ }
+ pipeline->uniform_count = ubo_count;
+
+ pipeline->renderpass = description.renderpass;
+ pipeline->wireframe = description.wireframe;
+
+ return pipeline;
+}
+
+void GraphicsPipeline_Destroy(GPU_Pipeline* pipeline) {}
+
+GPU_CmdEncoder GPU_CmdEncoder_Create() {
+ GPU_CmdEncoder encoder = { 0 };
+ return encoder;
+}
+
+
+BufferHandle GPU_BufferCreate(u64 size, GPU_BufferType buf_type, GPU_BufferFlags flags, const void *data) {
+ // "allocating" the cpu-side buffer struct
+ BufferHandle handle;
+ GPU_Buffer* buffer = Buffer_pool_alloc(&context.resource_pools, &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;
+}
+
+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;
+}
+
+void GPU_TextureDestroy(TextureHandle handle) {
+ glDeleteTextures(1, &handle.raw);
+}
+
+// TODO: void GPU_TextureUpload(TextureHandle handle, size_t n_bytes, const void* data)
+
+bool GPU_Backend_BeginFrame() {
+ glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+void GPU_Backend_EndFrame() {
+ glfwSwapBuffers(context.window);
+}
diff --git a/src/ral/backends/opengl/backend_opengl.h b/src/ral/backends/opengl/backend_opengl.h
index 22162f3..4fbb4bb 100644
--- a/src/ral/backends/opengl/backend_opengl.h
+++ b/src/ral/backends/opengl/backend_opengl.h
@@ -39,11 +39,11 @@ typedef struct GPU_Renderpass {
typedef struct GPU_CmdEncoder {
GPU_Pipeline *pipeline;
-} GPU_CmdEncoder; // Recording
+} GPU_CmdEncoder; // Recording
-typedef struct gpu_cmd_buffer {
+typedef struct GPU_CmdBuffer {
void *pad;
-} gpu_cmd_buffer; // Ready for submission
+} GPU_CmdBuffer; // Ready for submission
typedef struct GPU_Buffer {
union {
diff --git a/src/ral/ral_common.c b/src/ral/ral_common.c
index 89d475b..8ff282e 100644
--- a/src/ral/ral_common.c
+++ b/src/ral/ral_common.c
@@ -1,7 +1,7 @@
#include "ral_common.h"
#include "ral_impl.h"
-void backend_pools_init(arena* a, GPU_BackendPools* backend_pools) {
+void BackendPools_Init(arena* a, GPU_BackendPools* backend_pools) {
PipelineLayout_pool pipeline_layout_pool =
PipelineLayout_pool_create(a, MAX_PIPELINES, sizeof(GPU_PipelineLayout));
backend_pools->pipeline_layouts = pipeline_layout_pool;
@@ -11,9 +11,51 @@ void backend_pools_init(arena* a, GPU_BackendPools* backend_pools) {
backend_pools->renderpasses = rpass_pool;
}
-void resource_pools_init(arena* a, struct ResourcePools* res_pools) {
+void ResourcePools_Init(arena* a, struct ResourcePools* res_pools) {
Buffer_pool buf_pool = Buffer_pool_create(a, MAX_BUFFERS, sizeof(GPU_Buffer));
res_pools->buffers = buf_pool;
Texture_pool tex_pool = Texture_pool_create(a, MAX_TEXTURES, sizeof(GPU_Texture));
res_pools->textures = tex_pool;
}
+
+VertexDescription static_3d_vertex_description() {
+ VertexDescription builder = { .debug_label = "Standard static 3d vertex format" };
+ VertexDesc_AddAttr(&builder, "inPosition", ATTR_F32x3);
+ VertexDesc_AddAttr(&builder, "inNormal", ATTR_F32x3);
+ VertexDesc_AddAttr(&builder, "inTexCoords", ATTR_F32x2);
+ builder.use_full_vertex_size = true;
+ return builder;
+}
+
+void VertexDesc_AddAttr(VertexDescription* builder, const char* name, VertexAttribType type) {
+ u32 i = builder->attributes_count;
+
+ size_t size = VertexAttribSize(type);
+ builder->attributes[i] = type;
+ builder->stride += size;
+ builder->attr_names[i] = name;
+
+ builder->attributes_count++;
+}
+
+size_t VertexAttribSize(VertexAttribType attr) {
+ switch (attr) {
+ case ATTR_F32:
+ case ATTR_U32:
+ case ATTR_I32:
+ return 4;
+ case ATTR_F32x2:
+ case ATTR_U32x2:
+ case ATTR_I32x2:
+ return 8;
+ case ATTR_F32x3:
+ case ATTR_U32x3:
+ case ATTR_I32x3:
+ return 12;
+ case ATTR_F32x4:
+ case ATTR_U32x4:
+ case ATTR_I32x4:
+ return 16;
+ break;
+ }
+}
diff --git a/src/ral/ral_common.h b/src/ral/ral_common.h
index 1088404..0f7c1b7 100644
--- a/src/ral/ral_common.h
+++ b/src/ral/ral_common.h
@@ -1,3 +1,6 @@
+/**
+ * @brief Common functions that don't actually depend on the specific backend
+*/
#pragma once
#include "defines.h"
#include "buf.h"
@@ -5,7 +8,6 @@
#include "ral_types.h"
#include "ral_impl.h"
-
TYPED_POOL(GPU_Buffer, Buffer);
TYPED_POOL(GPU_Texture, Texture);
TYPED_POOL(GPU_PipelineLayout, PipelineLayout);
@@ -17,23 +19,23 @@ TYPED_POOL(GPU_Renderpass, Renderpass);
#define TEXTURE_GET(h) (texture_pool_get(&context.resource_pools->textures, h))
// --- Pools
-typedef struct GPU_BackendPools{
+typedef struct GPU_BackendPools {
Pipeline_pool pipelines;
PipelineLayout_pool pipeline_layouts;
Renderpass_pool renderpasses;
} GPU_BackendPools;
-void backend_pools_init(arena* a, GPU_BackendPools* backend_pools);
+void BackendPools_Init(arena* a, GPU_BackendPools* backend_pools);
struct ResourcePools {
Buffer_pool buffers;
Texture_pool textures;
};
-void resource_pools_init(arena* a, struct ResourcePools* res_pools);
-
+typedef struct ResourcePools ResourcePools;
+void ResourcePools_Init(arena* a, struct ResourcePools* res_pools);
// --- Vertex formats
-bytebuffer vertices_as_bytebuffer(arena* a, VertexFormat format, Vertex_darray* vertices);
-
-void vertex_desc_add(VertexDescription* builder, const char* name, VertexAttribType type);
VertexDescription static_3d_vertex_description();
-size_t vertex_attrib_size(VertexAttribType attr);
+
+void VertexDesc_AddAttr(VertexDescription* builder, const char* name, VertexAttribType type);
+
+size_t VertexAttribSize(VertexAttribType attr);
diff --git a/src/ral/ral_impl.h b/src/ral/ral_impl.h
index 4d1c17a..a896eff 100644
--- a/src/ral/ral_impl.h
+++ b/src/ral/ral_impl.h
@@ -2,7 +2,9 @@
* @brief
*/
#pragma once
+#include "buf.h"
#include "defines.h"
+#include "ral_common.h"
#include "ral_types.h"
struct GLFWwindow;
@@ -18,7 +20,9 @@ typedef struct GPU_CmdBuffer GPU_CmdBuffer; // Ready for submission
typedef struct GPU_Buffer GPU_Buffer;
typedef struct GPU_Texture GPU_Texture;
-bool GPU_Backend_Init(const char* window_name, struct GLFWwindow* window);
+struct ResourcePools;
+
+bool GPU_Backend_Init(const char* window_name, struct GLFWwindow* window, struct ResourcePools* res_pools);
void GPU_Backend_Shutdown();
bool GPU_Device_Create(GPU_Device* out_device);
@@ -27,12 +31,54 @@ void GPU_Device_Destroy(GPU_Device* device);
bool GPU_Swapchain_Create(GPU_Swapchain* out_swapchain);
void GPU_Swapchain_Destroy(GPU_Swapchain* swapchain);
-GPU_Renderpass* GPU_Renderpass_Create(GPU_RenderpassDesc description);
-void GPU_Renderpass_Destroy(GPU_Renderpass* pass);
+PUB GPU_Renderpass* GPU_Renderpass_Create(GPU_RenderpassDesc description);
+PUB void GPU_Renderpass_Destroy(GPU_Renderpass* pass);
+
+PUB GPU_Pipeline* GPU_GraphicsPipeline_Create(GraphicsPipelineDesc description, GPU_Renderpass* renderpass);
+PUB void GraphicsPipeline_Destroy(GPU_Pipeline* pipeline);
+
+// --- Command buffer
+PUB GPU_CmdEncoder GPU_CmdEncoder_Create();
+PUB void GPU_CmdEncoder_Destroy(GPU_CmdEncoder* encoder);
+PUB void GPU_CmdEncoder_BeginRender(GPU_CmdEncoder* encoder, GPU_Renderpass* renderpass);
+PUB void GPU_CmdEncoder_EndRender(GPU_CmdEncoder* encoder);
+PUB GPU_CmdEncoder* GPU_GetDefaultEncoder();
+PUB void GPU_QueueSubmit(GPU_CmdBuffer* cmd_buffer);
+
+// --- Buffers
+PUB BufferHandle GPU_BufferCreate(u64 size, GPU_BufferType buf_type, GPU_BufferFlags flags, const void* data);
+PUB void GPU_BufferDestroy(BufferHandle handle);
+PUB void GPU_BufferUpload(BufferHandle buffer, size_t n_bytes, const void* data);
+
+// --- Textures
+PUB TextureHandle GPU_TextureCreate(TextureDesc desc, bool create_view, const void* data);
+PUB void GPU_TextureDestroy(TextureHandle handle);
+PUB void GPU_TextureUpload(TextureHandle handle, size_t n_bytes, const void* data);
+
+// --- Data copy commands
+// TODO: Rename these to reflect current coding style
+void encode_buffer_copy(GPU_CmdEncoder* encoder, BufferHandle src, u64 src_offset,
+ BufferHandle dst, u64 dst_offset, u64 copy_size);
+void buffer_upload_bytes(BufferHandle gpu_buf, bytebuffer cpu_buf, u64 offset, u64 size);
+
+void copy_buffer_to_buffer_oneshot(BufferHandle src, u64 src_offset, BufferHandle dst,
+ u64 dst_offset, u64 copy_size);
+void copy_buffer_to_image_oneshot(BufferHandle src, TextureHandle dst);
+
+// --- Render commands
+PUB void GPU_EncodeBindPipeline(GPU_CmdEncoder* encoder, GPU_Pipeline* pipeline);
+PUB void GPU_EncodeBindShaderData(GPU_CmdEncoder* encoder, u32 group, ShaderData* data);
+void GPU_EncodeSetDefaults(GPU_CmdEncoder* encoder);
+PUB void GPU_EncodeSetVertexBuffer(GPU_CmdEncoder* encoder, BufferHandle buf);
+PUB void GPU_EncodeSetIndexBuffer(GPU_CmdEncoder* encoder, BufferHandle buf);
+PUB void GPU_EncodeDraw(GPU_CmdEncoder* encoder, u64 count);
+PUB void GPU_EncodeDrawIndexed(GPU_CmdEncoder* encoder, u64 index_count);
-GPU_Pipeline* GPU_GraphicsPipeline_Create(GraphicsPipelineDesc description, GPU_Renderpass* renderpass);
-void GraphicsPipeline_Destroy(GPU_Pipeline* pipeline);
+// --- 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
diff --git a/src/ral/ral_types.h b/src/ral/ral_types.h
index 0ba7f87..188951a 100644
--- a/src/ral/ral_types.h
+++ b/src/ral/ral_types.h
@@ -176,7 +176,7 @@ typedef struct ShaderDataLayout {
size_t binding_count;
} ShaderDataLayout;
-typedef ShaderDataLayout (*FN_GetBindingLayout)(void);
+typedef ShaderDataLayout (*FN_GetBindingLayout)(void* data);
typedef struct ShaderData {
FN_GetBindingLayout get_layout;
@@ -197,7 +197,6 @@ typedef enum PrimitiveTopology {
typedef enum CullMode { CULL_BACK_FACE, CULL_FRONT_FACE, CULL_COUNT } CullMode;
typedef struct GraphicsPipelineDesc {
- // GPU_Renderpass* renderpass -> takes a renderpass in the create function
const char* debug_name;
VertexDescription vertex_desc;
ShaderDesc vs; /** @brief Vertex shader stage */
@@ -205,7 +204,7 @@ typedef struct GraphicsPipelineDesc {
// Roughly equivalent to a descriptor set layout each. each layout can have multiple bindings
// examples:
- // - uniform buffer reprensenting view projection matrix
+ // - uniform buffer representing view projection matrix
// - texture for shadow map
ShaderData data_layouts[MAX_SHADER_DATA_LAYOUTS];
u32 data_layouts_count;