From 9b1c7caceff6af24d76146bcc7a4495ff9ef3ede Mon Sep 17 00:00:00 2001 From: onelin Date: Sat, 15 Nov 2025 21:33:50 +0100 Subject: Simplify render command buffer --- src/CMakeLists.txt | 1 - src/api/daw.h | 1 - src/daw.c | 2 +- src/gl.c | 1 - src/include/daw/daw.h | 1 + src/include/daw/keycodes.h | 8 +- src/include/daw/platform.h | 56 ----------- src/include/daw/platform_glfw.h | 1 - src/include/daw/rendering.h | 86 +++++------------ src/include/daw/utils.h | 10 -- src/include/daw/window.h | 54 ++++++++++- src/input.c | 1 - src/misc.c | 2 - src/platform_glfw.c | 2 +- src/rendering.c | 204 +++++++++++++++------------------------- src/resources.c | 2 +- 16 files changed, 154 insertions(+), 278 deletions(-) delete mode 100644 src/include/daw/platform.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2e915f8..e721bff 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,7 +24,6 @@ add_library(${PROJECT_NAME} api/daw.h # Types and (internal) interfaces - include/daw/platform.h include/daw/types.h # Utility algorithms & datastructures diff --git a/src/api/daw.h b/src/api/daw.h index 25ec177..2676170 100644 --- a/src/api/daw.h +++ b/src/api/daw.h @@ -7,7 +7,6 @@ extern "C" { #include #include -#include /* Essential functions */ diff --git a/src/daw.c b/src/daw.c index b632466..163f484 100644 --- a/src/daw.c +++ b/src/daw.c @@ -213,7 +213,7 @@ i32 engine_run(Instance* p, StateType initial_state, void* state_arg) { if (next_state != STATE_null) { if (next_state == STATE_quit) break; - drawcall_reset(); + window_reset_drawing(); void* retval = State_free(state, mem); memory_clear(mem); diff --git a/src/gl.c b/src/gl.c index 0eb4744..5178ef9 100644 --- a/src/gl.c +++ b/src/gl.c @@ -8,7 +8,6 @@ #include #include -#include #include extern Instance* GLOBAL_PLATFORM; diff --git a/src/include/daw/daw.h b/src/include/daw/daw.h index acbbcd9..ca611b3 100644 --- a/src/include/daw/daw.h +++ b/src/include/daw/daw.h @@ -38,6 +38,7 @@ typedef struct Instance { Camera *cam; /* Global resources that live from engine_init to engine_free */ + /* TODO: Add state-specific resources */ Resources* resources; memory* mem; diff --git a/src/include/daw/keycodes.h b/src/include/daw/keycodes.h index 869809f..5608741 100644 --- a/src/include/daw/keycodes.h +++ b/src/include/daw/keycodes.h @@ -6,16 +6,16 @@ extern "C" { // We want to reserve the following bytes marked with X for MODS, // one bit per MODIFIER (shift, control, alt, super): -// XXXX 0000 0000 0000 0000 0000 0000 0000 +// 0000 0000 XXXX 0000 0000 0000 0000 0000 // // We want to reserve the following bytes marked with X for ACTIONS // enumerate by action type, pressed, released, repeat -// 0000 0000 XXXX 0000 0000 0000 0000 0000 +// 0000 0000 0000 XXXX 0000 0000 0000 0000 // // We want to reserve the following bytes marked with X for the KEYCODE // 0000 0000 0000 0000 XXXX XXXX XXXX XXXX -#define KEY_MOD(x) (1 << (32-4 + x)) -#define ACTION(x) ((1 << (32-8)) + x) +#define ACTION(x) (1 << (16 + x)) +#define KEY_MOD(x) (1 << (20 + x)) typedef enum { KEY_SPACE = ' ', diff --git a/src/include/daw/platform.h b/src/include/daw/platform.h deleted file mode 100644 index c837c63..0000000 --- a/src/include/daw/platform.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef PLATFORM_H -#define PLATFORM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -// TODO: We only need the window once all the garbage in Instance is cleaned up. -#include - -#define DAW_WINDOW_VSYNC (1 << 0) -#define DAW_WINDOW_FULLSCREEN (1 << 1) -#define DAW_WINDOW_RESIZEABLE (1 << 2) - -// Whether or not it is clever to force API consistency using a struct like this -// can be debated, at the time of writing it seemed like a smart idea. - -// Platform libraries must implement a struct Platform: -struct Platform { - /* Initialize a window for the given platform. The rendering backend should - * also be initialized here. - * Parameters: - * const char* title: window title. - * ivec2 windowsize: the size in pixels for the new window. - * const u32 flags: window flags, such as static size and fullscreen. - * The flags are platform agnostic and needs to be - * converted to the specific library - * Returns: - * A pointer to a struct Window, NULL on error. - */ - Window* (*window_init)(const char *restrict title, ivec2 windowsize, const u32 flags); - - /* Destroy, close, and free up resources related to the window and the - * platform library specific resources. - */ - void (*window_destroy)(Window *restrict w); - - /* Resize the given window. Resize callbacks are handled by the wrapper - * implementation. - */ - void (*window_resize)(Window *restrict window, int width, int height); - - /* Return true if the platform has ordered the window to exit. */ - bool (*window_should_close)(Window *restrict w); - - /* Poll events on the window from the operating system. */ - void (*window_poll)(void); -}; - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/include/daw/platform_glfw.h b/src/include/daw/platform_glfw.h index 1136a9f..01964c9 100644 --- a/src/include/daw/platform_glfw.h +++ b/src/include/daw/platform_glfw.h @@ -8,7 +8,6 @@ extern "C" { #include #include -#include #include Window* window_init_glfw(const char *restrict windowtitle, ivec2 windowsize, const u32 flags); diff --git a/src/include/daw/rendering.h b/src/include/daw/rendering.h index 9f53f78..9c4b647 100644 --- a/src/include/daw/rendering.h +++ b/src/include/daw/rendering.h @@ -6,7 +6,7 @@ extern "C" { #endif #include -#include +//#include #include @@ -15,14 +15,6 @@ extern "C" { #define RGB(_r, _g, _b) RGBA(_r, _g, _b, 0xFF) /* Types */ -/* TODO: Cleanup these types. */ -typedef struct { - u8 r; - u8 g; - u8 b; - u8 a; -} Engine_color; - typedef struct { /* Maybe implement types, such as `atlas` (default), `standalone`, or * something idk. */ @@ -31,11 +23,6 @@ typedef struct { i32 height; } Texture; -typedef struct { - u32 texture_id; - ivec2 coord; -} Sprite; - typedef enum { Shader_Error, @@ -63,33 +50,33 @@ typedef enum { ShaderBufferFlag_none = 0x00, // First 3 bytes describe the access frequency. - ShaderBuffer_AccessFrequency_stream = 1, // 1 - ShaderBuffer_AccessFrequency_static = 2, // 2 - ShaderBuffer_AccessFrequency_dynamic = 3, // 3 + ShaderBuffer_AccessFrequency_stream = 1, // 1 + ShaderBuffer_AccessFrequency_static = 2, // 2 + ShaderBuffer_AccessFrequency_dynamic = 3, // 3 // Next 3 bytes describe the access type. - ShaderBuffer_AccessType_draw = 1 << 3, // 8 - ShaderBuffer_AccessType_read = 2 << 3, // 16 - ShaderBuffer_AccessType_copy = 3 << 3, // 24 + ShaderBuffer_AccessType_draw = 1 << 3, // 8 + ShaderBuffer_AccessType_read = 2 << 3, // 16 + ShaderBuffer_AccessType_copy = 3 << 3, // 24 // Next 3 bytes describe the buffer type - ShaderBuffer_Type_vertexData = 1 << 6, // 64 - ShaderBuffer_Type_vertexPosition = 2 << 6, // 128 - ShaderBuffer_Type_vertexIndex = 3 << 6, // 192 + ShaderBuffer_Type_vertexData = 1 << 6, // 64 + ShaderBuffer_Type_vertexPosition = 2 << 6, // 128 + ShaderBuffer_Type_vertexIndex = 3 << 6, // 192 // Next 4 bytes are designated for the data type - ShaderBuffer_DataType_nil = 1 << 9, // 512 + ShaderBuffer_DataType_nil = 1 << 9, // 512 - ShaderBuffer_DataType_f32 = 2 << 9, // 1024 - ShaderBuffer_DataType_f64 = 3 << 9, // 1536 + ShaderBuffer_DataType_f32 = 2 << 9, // 1024 + ShaderBuffer_DataType_f64 = 3 << 9, // 1536 - ShaderBuffer_DataType_i8 = 4 << 9, // 2048 - ShaderBuffer_DataType_i16 = 5 << 9, // 2560 - ShaderBuffer_DataType_i32 = 6 << 9, // 3072 - ShaderBuffer_DataType_i64 = 7 << 9, // 3584 + ShaderBuffer_DataType_i8 = 4 << 9, // 2048 + ShaderBuffer_DataType_i16 = 5 << 9, // 2560 + ShaderBuffer_DataType_i32 = 6 << 9, // 3072 + ShaderBuffer_DataType_i64 = 7 << 9, // 3584 - ShaderBuffer_DataType_u8 = 8 << 9, // 4096 - ShaderBuffer_DataType_u16 = 9 << 9, // 4608 + ShaderBuffer_DataType_u8 = 8 << 9, // 4096 + ShaderBuffer_DataType_u16 = 9 << 9, // 4608 ShaderBuffer_DataType_u32 = 10 << 9, // 5120 ShaderBuffer_DataType_u64 = 11 << 9, // 5632 } ShaderBufferFlag; @@ -216,12 +203,6 @@ u32 ShaderBuffer_get_gl_type(u64 flags); u32 ShaderBuffer_get_gl_accesstype(u64 flags); u32 ShaderBuffer_get_gl_datatype(u64 flags); -/* Rendering functions */ -void render_begin(Window* w); -void render_present(Window* w); -void drawcall_reset(void); -void render(Window* w); - /* Misc */ void r_perspective(f32 fov, Camera *c); void r_perspective_ortho(f32 sz, Camera *c); @@ -231,35 +212,12 @@ void r_reset_camera(Camera* c); //void window_size_callback(GLFWwindow* window, i32 width, i32 height); -void engine_draw_sprite(Sprite* s, ivec2* pos, f32 scale); -void engine_draw_sprite_ex(Sprite* s, ivec2* pos, f32 scale, - Engine_color colormod); void engine_draw_model(RenderObject* o, vec3 pos); -Sprite sprite_new(u64 tid, u8 coord); - -typedef enum { - RenderDrawCallType_Text, - RenderDrawCallType_Sprite, - RenderDrawCallType_Model, -} RenderDrawCallType; - typedef struct { - RenderDrawCallType type; - union { - void* data; - struct { - Sprite* sprite; - i32 x; - i32 y; - f32 scale; - } sprite; - struct { - RenderObject* model; - vec3 pos; - f32 scale; - } model; - } data; + vec3 pos; + f32 scale; + RenderObject* model; } RenderDrawCall; // TODO make all the shader buffers a list diff --git a/src/include/daw/utils.h b/src/include/daw/utils.h index 5f735e9..046b4bc 100644 --- a/src/include/daw/utils.h +++ b/src/include/daw/utils.h @@ -11,16 +11,6 @@ extern "C" { #define MIN(a, b) ((a < b) ? (a) : (b)) #define MAX(a, b) ((a > b) ? (a) : (b)) -#define MASK_TL (1 << 0) -#define MASK_T (1 << 1) -#define MASK_TR (1 << 2) -#define MASK_L (1 << 3) -#define MASK_C (1 << 4) -#define MASK_R (1 << 5) -#define MASK_BL (1 << 6) -#define MASK_B (1 << 7) -#define MASK_BR (1 << 8) - /* Linear interpolate */ f32 lerp(f32 dt, f32 a, f32 b); i32 int_lerp(f32 dt, i32 a, i32 b); diff --git a/src/include/daw/window.h b/src/include/daw/window.h index 2924448..83280ec 100644 --- a/src/include/daw/window.h +++ b/src/include/daw/window.h @@ -10,9 +10,7 @@ extern "C" { #include #include -#ifndef ENGINE_RENDERING_WINDOW_H_EXCLUDE_EXTERNS -extern u64 (*get_time)(void); -#endif +#include typedef enum { WINDOW_FRAMEWORK_NONE = 0, @@ -43,10 +41,58 @@ typedef struct { i_ctx** bindings; } Window; -#include +#define DAW_WINDOW_VSYNC (1 << 0) +#define DAW_WINDOW_FULLSCREEN (1 << 1) +#define DAW_WINDOW_RESIZEABLE (1 << 2) + +// Whether or not it is clever to force API consistency using a struct like this +// can be debated, at the time of writing it seemed like a smart idea. + +// Platform libraries must implement a struct Platform: +struct Platform { + /* Initialize a window for the given platform. The rendering backend should + * also be initialized here. + * Parameters: + * const char* title: window title. + * ivec2 windowsize: the size in pixels for the new window. + * const u32 flags: window flags, such as static size and fullscreen. + * The flags are platform agnostic and needs to be + * converted to the specific library + * Returns: + * A pointer to a struct Window, NULL on error. + */ + Window* (*window_init)(const char *restrict title, ivec2 windowsize, const u32 flags); + + /* Destroy, close, and free up resources related to the window and the + * platform library specific resources. + */ + void (*window_destroy)(Window *restrict w); + + /* Resize the given window. Resize callbacks are handled by the wrapper + * implementation. + */ + void (*window_resize)(Window *restrict window, int width, int height); + + /* Return true if the platform has ordered the window to exit. */ + bool (*window_should_close)(Window *restrict w); + + /* Poll events on the window from the operating system. */ + void (*window_poll)(void); +}; + + +#ifndef ENGINE_RENDERING_WINDOW_H_EXCLUDE_EXTERNS +extern u64 (*get_time)(void); +#endif Window* Window_new(const struct Platform *p, const char *restrict title, Window_framework framework, Window_renderer renderer, ivec2 size, u32 flags); +/* Rendering functions */ +void render_begin(Window* w); +void render_present(Window* w); +void window_reset_drawing(void); +void render(Window* w); + void get_mousepos(double *x, double *y); #ifdef __cplusplus diff --git a/src/input.c b/src/input.c index b33a1fa..bdaa169 100644 --- a/src/input.c +++ b/src/input.c @@ -7,7 +7,6 @@ #include #include #include -#include #include extern input_callback_t* callbacks[128]; diff --git a/src/misc.c b/src/misc.c index 16c0cfb..19920ab 100644 --- a/src/misc.c +++ b/src/misc.c @@ -1,8 +1,6 @@ #include #include -#include - #include #include diff --git a/src/platform_glfw.c b/src/platform_glfw.c index 211df47..96b533c 100644 --- a/src/platform_glfw.c +++ b/src/platform_glfw.c @@ -11,7 +11,7 @@ #include -#include +#include static void window_resize_callback(GLFWwindow *restrict window, int width, int height); static void framebuffer_resize_callback(GLFWwindow *restrict window, int width, int height); diff --git a/src/rendering.c b/src/rendering.c index a37de58..25ee1fd 100644 --- a/src/rendering.c +++ b/src/rendering.c @@ -40,10 +40,10 @@ ShaderBufferDataType_size(u16 flags) { } } -ShaderBufferFlag ShaderBuffer_get_access_frequency(u64 flags) { return flags & (0b111 << 0); } -ShaderBufferFlag ShaderBuffer_get_access_type(u64 flags) { return flags & (0b111 << 3); } -ShaderBufferFlag ShaderBuffer_get_type(u64 flags) { return flags & (0b111 << 6); } -ShaderBufferFlag ShaderBuffer_get_data_type(u64 flags) { return flags & (0b1111 << 9); } +ShaderBufferFlag ShaderBuffer_get_access_frequency(u64 flags) { return flags & ( 7 << 0); } +ShaderBufferFlag ShaderBuffer_get_access_type(u64 flags) { return flags & ( 7 << 3); } +ShaderBufferFlag ShaderBuffer_get_type(u64 flags) { return flags & ( 7 << 6); } +ShaderBufferFlag ShaderBuffer_get_data_type(u64 flags) { return flags & (15 << 9); } u32 ShaderBuffer_get_gl_type(u64 flags) { switch(ShaderBuffer_get_type(flags)) { @@ -457,98 +457,88 @@ void render_present(Window* w) { for (i32 drawcall_idx = 0; drawcall_idx < drawcall_len; drawcall_idx++) { RenderDrawCall dc = drawcalls[drawcall_idx]; - switch (dc.type) { - case RenderDrawCallType_Sprite: { - // TODO render a quad - } break; - case RenderDrawCallType_Model: { + // bind shader program + // - set uniforms + // bind vertex array + // bind index buffer - // bind shader program - // - set uniforms - // bind vertex array - // bind index buffer + const RenderObject* const restrict o = dc.model; + vec3 pos; + glm_vec3_copy(dc.pos, pos); - RenderObject* o = dc.data.model.model; - vec3 pos; - glm_vec3_copy(dc.data.model.pos, pos); + gl->UseProgram(o->shader.program); + // TODO: Use texture atlas + gl->BindTextureUnit(0, o->texture); - gl->UseProgram(o->shader.program); - // TODO: Use texture atlas - gl->BindTextureUnit(0, o->texture); + { + mat4 model = GLM_MAT4_IDENTITY_INIT; + mat4 modelviewprojection; - { - mat4 model = GLM_MAT4_IDENTITY_INIT; - mat4 modelviewprojection; + model[3][0] = pos[0]; + model[3][1] = pos[1]; + model[3][2] = pos[2]; - model[3][0] = pos[0]; - model[3][1] = pos[1]; - model[3][2] = pos[2]; + // modelviewprojection = p * view * model + glm_mat4_mul(model, camera_matrix, modelviewprojection); - // modelviewprojection = p * view * model - glm_mat4_mul(model, camera_matrix, modelviewprojection); - - // TODO: Do this only once during initialization - gl->UniformMatrix4fv(o->mvp, 1, GL_FALSE, &modelviewprojection[0][0]); - gl->UniformMatrix4fv(o->model_position, 1, GL_FALSE, &model[0][0]); - } - - // TODO the buffers need to be abstracted a bit more - gl->BindVertexArray(o->vao); - - ShaderBuffer* ibo = NULL; - for (usize i = 0; i < o->buffer_len; i++) { - const u32 b_gl_type = ShaderBuffer_get_gl_type(o->buffer[i].buffertype); - if (b_gl_type == GL_ELEMENT_ARRAY_BUFFER) { - ibo = &o->buffer[i]; - } + // TODO: Do this only once during initialization + gl->UniformMatrix4fv(o->mvp, 1, GL_FALSE, &modelviewprojection[0][0]); + gl->UniformMatrix4fv(o->model_position, 1, GL_FALSE, &model[0][0]); + } - gl->EnableVertexAttribArray((u32)i); - gl->BindBuffer(b_gl_type, o->buffer[i].buffername); - gl->VertexAttribPointer( - // index of the attribute - (u32)i, - // number of component - (i32)o->buffer[i].components, - // type - ShaderBuffer_get_gl_datatype(o->buffer[i].buffertype), - // normalized? - GL_FALSE, - // stride - 0, - // array buffer offset - (void*)0 - ); - } + // TODO the buffers need to be abstracted a bit more + gl->BindVertexArray(o->vao); - // Draw the model ! - const i32 sz = (i32)(o->buffer->count * o->buffer->size_elem); - if (ibo) { - gl->DrawElements( - GL_TRIANGLES, - (i32)ibo->count, - ShaderBuffer_get_gl_datatype(ibo->buffertype), - (void*)0 - ); - } else { - // Starting from vertex 0; 3 vertices total -> 1 triangle - gl->DrawArrays(GL_TRIANGLES, 0, sz); + ShaderBuffer* ibo = NULL; + for (usize i = 0; i < o->buffer_len; i++) { + const u32 b_gl_type = ShaderBuffer_get_gl_type(o->buffer[i].buffertype); + if (b_gl_type == GL_ELEMENT_ARRAY_BUFFER) { + ibo = &o->buffer[i]; } - for (u32 i = 0; i < o->buffer_len; i++) { - gl->DisableVertexAttribArray(i); - } + gl->EnableVertexAttribArray((u32)i); + gl->BindBuffer(b_gl_type, o->buffer[i].buffername); + gl->VertexAttribPointer( + // index of the attribute + (u32)i, + // number of component + (i32)o->buffer[i].components, + // type + ShaderBuffer_get_gl_datatype(o->buffer[i].buffertype), + // normalized? + GL_FALSE, + // stride + 0, + // array buffer offset + (void*)0 + ); + } - gl->BindVertexArray(0); + // Draw the model ! + const i32 sz = (i32)(o->buffer->count * o->buffer->size_elem); + if (ibo) { + gl->DrawElements( + GL_TRIANGLES, + (i32)ibo->count, + ShaderBuffer_get_gl_datatype(ibo->buffertype), + (void*)0 + ); + } else { + // Starting from vertex 0; 3 vertices total -> 1 triangle + gl->DrawArrays(GL_TRIANGLES, 0, sz); + } - //if (i == 8) { - // printf("\r obj: %.3f", (double)(get_time() - t) * 1000.); - //} - } break; - default: - break; + for (u32 i = 0; i < o->buffer_len; i++) { + gl->DisableVertexAttribArray(i); } + + gl->BindVertexArray(0); + + //if (i == 8) { + // printf("\r obj: %.3f", (double)(get_time() - t) * 1000.); + //} } drawcall_len = 0; @@ -556,7 +546,7 @@ void render_present(Window* w) { glfwSwapBuffers(w->window); } -void drawcall_reset(void) { +void window_reset_drawing(void) { drawcall_len = 0; memset(drawcalls, 0, sizeof(RenderDrawCall) * drawcall_limit); } @@ -595,38 +585,6 @@ void r_reset_camera(Camera* c) { } } -void engine_draw_sprite(Sprite* s, ivec2* pos, f32 scale) { - if (drawcall_len + 1 >= drawcall_limit) return; -#ifdef _DEBUG - if (s == NULL) __asm__("int3;"); -#endif - drawcalls[drawcall_len++] = - (RenderDrawCall){.type = RenderDrawCallType_Sprite, - .data.sprite = { - .sprite = s, - .x = *pos[0], - .y = *pos[1], - .scale = scale, - //.mod = {0xFF, 0xFF, 0xFF, 0xFF}, - }}; -} - -void engine_draw_sprite_ex(Sprite* s, ivec2* pos, f32 scale, - Engine_color colormod) { - if (drawcall_len + 1 >= drawcall_limit) return; -#ifdef _DEBUG - if (s == NULL) __asm__("int3;"); -#endif - drawcalls[drawcall_len++] = (RenderDrawCall){ - .type = RenderDrawCallType_Sprite, - .data.sprite = { - .sprite = s, - .x = *pos[0], - .y = *pos[1], - .scale = scale, - //.mod = {colormod.r, colormod.g, colormod.b, colormod.a}, - }}; -} void engine_draw_model(RenderObject* o, vec3 pos) { if (drawcall_len + 1 >= drawcall_limit) return; @@ -634,29 +592,15 @@ void engine_draw_model(RenderObject* o, vec3 pos) { if (o == NULL) __asm__("int3;"); #endif RenderDrawCall dc = { - .type = RenderDrawCallType_Model, - .data.model = { .model = o, .scale = 1.f, - }}; - + }; - glm_vec3_copy(pos, dc.data.model.pos); + glm_vec3_copy(pos, dc.pos); drawcalls[drawcall_len++] = dc; } -Sprite sprite_new(u64 tid, u8 coord) { - const i32 ts = 16; - // FIXME; used to be - //((struct Resources*)GLOBAL_PLATFORM->data)->textures[tid]->tilesize; - return (Sprite){ - .texture_id = (u32)tid, - { - ts * (coord & 0x0F), - ts * ((coord & 0xF0) >> 4), - }}; -} Texture createTextureFromImageData(unsigned char* image_data, i32 width, i32 height, u8 components) { Window* restrict w = GLOBAL_PLATFORM->window; diff --git a/src/resources.c b/src/resources.c index 49b20e0..52adeae 100644 --- a/src/resources.c +++ b/src/resources.c @@ -3,8 +3,8 @@ #include #include #include -#include #include +#include extern Instance* GLOBAL_PLATFORM; -- cgit v1.3