summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/cube/ex_cube.c145
-rw-r--r--examples/triangle/ex_triangle.c22
-rw-r--r--src/renderer/ral.h1
-rw-r--r--src/renderer/ral_types.h61
-rw-r--r--src/systems/input.c1
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"