diff options
-rw-r--r-- | examples/cube/ex_cube.c | 145 | ||||
-rw-r--r-- | examples/triangle/ex_triangle.c | 22 | ||||
-rw-r--r-- | src/renderer/ral.h | 1 | ||||
-rw-r--r-- | src/renderer/ral_types.h | 61 | ||||
-rw-r--r-- | src/systems/input.c | 1 |
5 files changed, 213 insertions, 17 deletions
diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c new file mode 100644 index 0000000..71b7917 --- /dev/null +++ b/examples/cube/ex_cube.c @@ -0,0 +1,145 @@ +#include <glfw3.h> + +#include "buf.h" +#include "camera.h" +#include "core.h" +#include "file.h" +#include "log.h" +#include "maths.h" +#include "mem.h" +#include "ral.h" +#include "ral_types.h" +#include "render.h" + +extern core g_core; + +// Define the shader data +typedef struct mvp_uniforms { + mat4 model; + mat4 view; + mat4 projection; +} mvp_uniforms; + +shader_data_layout mvp_uniforms_layout(void* data) { + mvp_uniforms* d = (mvp_uniforms*)data; + bool has_data = data != NULL; + + shader_binding b1 = { + .label = "model", + .type = SHADER_BINDING_BYTES, + .stores_data = has_data, + .data = {.bytes = { .size = sizeof(mat4) }} + }; + shader_binding b2 = { + .label = "view", + .type = SHADER_BINDING_BYTES, + .stores_data = has_data, + .data = {.bytes = { .size = sizeof(mat4) }} + }; + shader_binding b3 = { + .label = "projection", + .type = SHADER_BINDING_BYTES, + .stores_data = has_data, + .data = {.bytes = { .size = sizeof(mat4) }} + }; + if (has_data) { + b1.data.bytes.data = &d->model; + b2.data.bytes.data = &d->view; + b3.data.bytes.data = &d->projection; + } + return (shader_data_layout ){.name = "mvp_uniforms", .bindings = { + b1, b2, b3 + }}; +} + +int main() { + core_bringup(); + arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); + + DEBUG("render capacity %d", g_core.default_scene.renderables->capacity); + + shader_data_layout mvp_layout = mvp_uniforms_layout(NULL); + + mvp_uniforms mvp_data = { + .model = mat4_ident(), + .view = mat4_ident(), + .projection = mat4_ident() + }; + + shader_data mvp_uniforms_data = { + .data = &mvp_data, + .shader_data_get_layout = &mvp_uniforms_layout + }; + + gpu_renderpass_desc pass_description = {}; + gpu_renderpass* renderpass = gpu_renderpass_create(&pass_description); + + str8 vert_path = str8lit("build/linux/x86_64/debug/triangle.vert.spv"); + str8 frag_path = str8lit("build/linux/x86_64/debug/triangle.frag.spv"); + str8_opt vertex_shader = str8_from_file(&scratch, vert_path); + str8_opt fragment_shader = str8_from_file(&scratch, frag_path); + if (!vertex_shader.has_value || !fragment_shader.has_value) { + ERROR_EXIT("Failed to load shaders from disk") + } + + struct graphics_pipeline_desc pipeline_description = { + .debug_name = "Basic Pipeline", + .vs = { .debug_name = "Triangle Vertex Shader", + .filepath = vert_path, + .code = vertex_shader.contents, + .is_spirv = true }, + .fs = { .debug_name = "Triangle Fragment Shader", + .filepath = frag_path, + .code = fragment_shader.contents, + .is_spirv = true }, + .renderpass = renderpass, + .wireframe = false, + .depth_test = false + }; + gpu_pipeline* gfx_pipeline = gpu_graphics_pipeline_create(pipeline_description); + + buffer_handle triangle_vert_buf = + gpu_buffer_create(sizeof(vertices), 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); + + // Main loop + while (!should_exit(&g_core)) { + glfwPollEvents(); + input_update(&g_core.input); + + // render_frame_begin(&g_core.renderer); + + if (!gpu_backend_begin_frame()) { + continue; + } + gpu_cmd_encoder* enc = gpu_get_default_cmd_encoder(); + // 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); + + // Record draw calls + encode_set_vertex_buffer(enc, triangle_vert_buf); + encode_set_index_buffer(enc, triangle_index_buf); + encode_bind_shader_data(enc, 0, &mvp_uniforms_data); + gpu_temp_draw(6); + + // End recording + gpu_cmd_encoder_end_render(enc); + + gpu_cmd_buffer buf = gpu_cmd_encoder_finish(enc); + gpu_queue_submit(&buf); + // Submit + gpu_backend_end_frame(); + + // render_frame_end(&g_core.renderer); + // glfwSwapBuffers(core->renderer.window); + } + + renderer_shutdown(&g_core.renderer); + + return 0; +} diff --git a/examples/triangle/ex_triangle.c b/examples/triangle/ex_triangle.c index dc82156..c6f0e54 100644 --- a/examples/triangle/ex_triangle.c +++ b/examples/triangle/ex_triangle.c @@ -12,8 +12,6 @@ #include "ral_types.h" #include "render.h" -// Example setting up a renderer - extern core g_core; const custom_vertex vertices[] = { @@ -28,8 +26,6 @@ int main() { core_bringup(); arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); - DEBUG("render capacity %d", g_core.default_scene.renderables->capacity); - gpu_renderpass_desc pass_description = {}; gpu_renderpass* renderpass = gpu_renderpass_create(&pass_description); @@ -65,19 +61,13 @@ int main() { // Main loop while (!should_exit(&g_core)) { - glfwPollEvents(); input_update(&g_core.input); - // render_frame_begin(&g_core.renderer); - - static f64 x = 0.0; - x += 0.01; - if (!gpu_backend_begin_frame()) { 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); @@ -86,18 +76,16 @@ int main() { // Record draw calls encode_set_vertex_buffer(enc, triangle_vert_buf); encode_set_index_buffer(enc, triangle_index_buf); - gpu_temp_draw(6); + encode_draw_indexed(enc, 6); // End recording gpu_cmd_encoder_end_render(enc); - gpu_cmd_buffer buf = gpu_cmd_encoder_finish(enc); - 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(); - - // render_frame_end(&g_core.renderer); - // glfwSwapBuffers(core->renderer.window); } renderer_shutdown(&g_core.renderer); diff --git a/src/renderer/ral.h b/src/renderer/ral.h index 2fb0166..38a653d 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -104,6 +104,7 @@ void buffer_upload_bytes(buffer_handle gpu_buf, bytebuffer cpu_buf, u64 offset, // render pass void encode_bind_pipeline(gpu_cmd_encoder* encoder, pipeline_kind kind, gpu_pipeline* pipeline); +void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* data); void encode_set_default_settings(gpu_cmd_encoder* encoder); void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf); void encode_set_index_buffer(gpu_cmd_encoder* encoder, buffer_handle buf); diff --git a/src/renderer/ral_types.h b/src/renderer/ral_types.h index 2fa8258..230afc3 100644 --- a/src/renderer/ral_types.h +++ b/src/renderer/ral_types.h @@ -120,6 +120,67 @@ typedef struct custom_vertex { vec3 color; } custom_vertex; +// Vertex attributes +typedef enum vertex_attrib_type { + ATTR_F32, + ATTR_F32x2, + ATTR_F32x3, + ATTR_F32x4, + ATTR_U32, + ATTR_U32x2, + ATTR_U32x3, + ATTR_U32x4, + ATTR_I32, + ATTR_I32x2, + ATTR_I32x3, + ATTR_I32x4, +} vertex_attrib_type; + +typedef enum shader_binding_type { + SHADER_BINDING_BUFFER, + SHADER_BINDING_TEXTURE, + SHADER_BINDING_BYTES, + SHADER_BINDING_COUNT +} shader_binding_type; + +typedef struct shader_binding { + const char* label; + shader_binding_type type; + bool stores_data; /** @brief if this is true then the shader binding has references to live data, + if false then its just being used to describe a layout and .data + should be zeroed */ + union { + struct { + buffer_handle handle; + } buffer; + struct { + void* data; + size_t size; + } bytes; + } data; +} shader_binding; + +#define MAX_LAYOUT_BINDINGS 8 + +/** @brief A list of bindings that describe what data a shader / pipeline expects + @note This roughly correlates to a descriptor set layout in Vulkan +*/ +typedef struct shader_data_layout { + char* name; + shader_binding bindings[MAX_LAYOUT_BINDINGS]; +} shader_data_layout; + +typedef struct shader_data { + shader_data_layout (*shader_data_get_layout)(void* data); + void* data; +} shader_data; + +/* + Usage: + 1. When we create the pipeline, we must call a function that return a layout without .data fields + 2. When binding +*/ + typedef enum gpu_cull_mode { CULL_BACK_FACE, CULL_FRONT_FACE, CULL_COUNT } gpu_cull_mode; // ? How to tie together materials and shaders diff --git a/src/systems/input.c b/src/systems/input.c index 5df1159..0c8f768 100644 --- a/src/systems/input.c +++ b/src/systems/input.c @@ -32,6 +32,7 @@ bool input_system_init(input_state *input, GLFWwindow *window) { void input_system_shutdown(input_state *input) {} void input_update(input_state *input) { + glfwPollEvents(); // --- update keyboard input // if we go from un-pressed -> pressed, set as "just pressed" |