summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/triangle/ex_triangle.c39
-rw-r--r--src/renderer/backends/backend_dx11.h3
-rw-r--r--src/renderer/backends/backend_vulkan.c142
-rw-r--r--src/renderer/backends/backend_vulkan.h11
-rw-r--r--src/renderer/backends/vulkan_helpers.h7
-rw-r--r--src/renderer/bind_group_layouts.h30
-rw-r--r--src/renderer/ral.h22
-rw-r--r--src/renderer/ral_types.h6
-rw-r--r--src/renderer/render.h1
-rw-r--r--src/renderer/render_types.h5
-rw-r--r--src/renderer/renderpasses.h31
11 files changed, 274 insertions, 23 deletions
diff --git a/examples/triangle/ex_triangle.c b/examples/triangle/ex_triangle.c
index 4e31313..9b993c1 100644
--- a/examples/triangle/ex_triangle.c
+++ b/examples/triangle/ex_triangle.c
@@ -1,27 +1,52 @@
#include <glfw3.h>
+#include "backend_vulkan.h"
#include "camera.h"
#include "core.h"
+#include "file.h"
+#include "log.h"
#include "maths.h"
+#include "mem.h"
+#include "ral.h"
#include "render.h"
+// Example setting up a renderer
+
int main() {
core* core = core_bringup();
+ arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024);
+
+ gpu_renderpass_desc pass_description = {};
+ gpu_renderpass* renderpass = gpu_renderpass_create(&pass_description);
- camera camera = camera_create(vec3_create(0, 0, 20), VEC3_NEG_Z, VEC3_Y, deg_to_rad(45.0));
+ str8_opt vertex_shader = str8_from_file(&scratch, str8lit("assets/shaders/triangle.vert"));
+ str8_opt fragment_shader = str8_from_file(&scratch, str8lit("assets/shaders/triangle.frag"));
+ 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 = str8lit("assets/shaders/triangle.vert"),
+ .glsl = vertex_shader.contents },
+ .fs = { .debug_name = "Triangle Fragment Shader",
+ .filepath = str8lit("assets/shaders/triangle.frag"),
+ .glsl = fragment_shader.contents },
+ .renderpass = renderpass,
+ .wireframe = false,
+ .depth_test = false
+ };
+ gpu_pipeline* gfx_pipeline = gpu_graphics_pipeline_create(pipeline_description);
// Main loop
- while (!glfwWindowShouldClose(core->renderer.window)) {
+ while (!should_exit(core)) {
input_update(&core->input);
- // threadpool_process_results(&core->threadpool, 1);
render_frame_begin(&core->renderer);
- static f32 x = 0.0;
+ static f64 x = 0.0;
x += 0.01;
- mat4 model = mat4_translation(vec3(x, 0, 0));
-
- gfx_backend_draw_frame(&core->renderer, &camera, model, NULL);
// insert work here
diff --git a/src/renderer/backends/backend_dx11.h b/src/renderer/backends/backend_dx11.h
index e076659..8e3a513 100644
--- a/src/renderer/backends/backend_dx11.h
+++ b/src/renderer/backends/backend_dx11.h
@@ -6,8 +6,7 @@
#define GPU_SWAPCHAIN_IMG_COUNT 2
-typedef struct gpu_swapchain {
-} gpu_swapchain;
+// typedef struct gpu_swapchain gpu_swapchain;
typedef struct gpu_device {
// VkPhysicalDevice physical_device;
diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c
index 2502dd2..ae857a0 100644
--- a/src/renderer/backends/backend_vulkan.c
+++ b/src/renderer/backends/backend_vulkan.c
@@ -141,7 +141,7 @@ bool gpu_swapchain_create(gpu_swapchain* out_swapchain) {
VkSwapchainCreateInfoKHR swapchain_create_info = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR };
- // swapchain_create_info.minImageCount =
+ // swapchain_create_info.minImageCount =
VK_CHECK(vkCreateSwapchainKHR(context.device->logical_device, &swapchain_create_info,
context.allocator, &out_swapchain->handle));
@@ -149,6 +149,11 @@ bool gpu_swapchain_create(gpu_swapchain* out_swapchain) {
}
gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description) {
+ // Allocate
+ gpu_pipeline_layout* layout = malloc(sizeof(gpu_pipeline_layout));
+ gpu_pipeline* pipeline = malloc(sizeof(gpu_pipeline));
+
+ // Viewport
VkViewport viewport = { .x = 0,
.y = 0,
.width = (f32)context.screen_width,
@@ -158,11 +163,6 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip
VkRect2D scissor = { .offset = { .x = 0, .y = 0 },
.extent = { .width = context.screen_width,
.height = context.screen_height } };
-
- // TODO: Attributes
-
- // TODO: layouts
-
VkPipelineViewportStateCreateInfo viewport_state = {
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO
};
@@ -170,12 +170,136 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip
viewport_state.pViewports = &viewport;
viewport_state.scissorCount = 1;
viewport_state.pScissors = &scissor;
+
+ // Rasterizer
+ VkPipelineRasterizationStateCreateInfo rasterizer_create_info = {
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO
+ };
+ rasterizer_create_info.depthClampEnable = VK_FALSE;
+ rasterizer_create_info.rasterizerDiscardEnable = VK_FALSE;
+ rasterizer_create_info.polygonMode =
+ description.wireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;
+ rasterizer_create_info.lineWidth = 1.0f;
+ rasterizer_create_info.cullMode = VK_CULL_MODE_BACK_BIT;
+ rasterizer_create_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
+ rasterizer_create_info.depthBiasEnable = VK_FALSE;
+ rasterizer_create_info.depthBiasConstantFactor = 0.0;
+ rasterizer_create_info.depthBiasClamp = 0.0;
+ rasterizer_create_info.depthBiasSlopeFactor = 0.0;
+
+ // Multisampling
+ VkPipelineMultisampleStateCreateInfo ms_create_info = {
+ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO
+ };
+ ms_create_info.sampleShadingEnable = VK_FALSE;
+ ms_create_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ ms_create_info.minSampleShading = 1.0;
+ ms_create_info.pSampleMask = 0;
+ ms_create_info.alphaToCoverageEnable = VK_FALSE;
+ ms_create_info.alphaToOneEnable = VK_FALSE;
+
+ // Depth and stencil testing
+ VkPipelineDepthStencilStateCreateInfo depth_stencil = {
+ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO
+ };
+ depth_stencil.depthTestEnable = description.depth_test ? VK_TRUE : VK_FALSE;
+ depth_stencil.depthWriteEnable = description.depth_test ? VK_TRUE : VK_FALSE;
+ depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS;
+ depth_stencil.depthBoundsTestEnable = VK_FALSE;
+ depth_stencil.stencilTestEnable = VK_FALSE;
+ depth_stencil.pNext = 0;
+
+ // TODO: Blending
+
+ // TODO: Vertex Input
+
+ // TODO: Attributes
+
+ // TODO: layouts
+ VkPipelineLayoutCreateInfo pipeline_layout_create_info = {
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO
+ };
+ pipeline_layout_create_info.setLayoutCount = 0;
+ pipeline_layout_create_info.pSetLayouts = NULL;
+ pipeline_layout_create_info.pushConstantRangeCount = 0;
+ pipeline_layout_create_info.pPushConstantRanges = NULL;
+ VK_CHECK(vkCreatePipelineLayout(context.device->logical_device, &pipeline_layout_create_info,
+ context.allocator, &layout->handle));
+ pipeline->layout_handle = layout->handle; // keep a copy of the layout on the pipeline object
+
+ VkGraphicsPipelineCreateInfo pipeline_create_info = {
+ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO
+ };
+ // pipeline_create_info.stageCount = stage_count;
+ // pipeline_create_info.pStages = stages;
+ // pipeline_create_info.pVertexInputState = &vertex_input_info;
+ // pipeline_create_info.pInputAssemblyState = &input_assembly;
+
+ // pipeline_create_info.pViewportState = &viewport_state;
+ // pipeline_create_info.pRasterizationState = &rasterizer_create_info;
+ // pipeline_create_info.pMultisampleState = &ms_create_info;
+ // pipeline_create_info.pDepthStencilState = &depth_stencil;
+ // pipeline_create_info.pColorBlendState = &color_blend;
+ // pipeline_create_info.pDynamicState = &dynamic_state;
+ // pipeline_create_info.pTessellationState = 0;
+
+ // pipeline_create_info.layout = out_pipeline->layout;
+
+ // pipeline_create_info.renderPass = renderpass->handle;
+ // pipeline_create_info.subpass = 0;
+ // pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE;
+ // pipeline_create_info.basePipelineIndex = -1;
+
+ VkResult result =
+ vkCreateGraphicsPipelines(context.device->logical_device, VK_NULL_HANDLE, 1,
+ &pipeline_create_info, context.allocator, &pipeline->handle);
+ if (result != VK_SUCCESS) {
+ FATAL("graphics pipeline creation failed. its fked mate");
+ ERROR_EXIT("Doomed");
+ }
+
+ return pipeline;
}
-gpu_renderpass* gpu_renderpass_create() {
- // Allocate it
+gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description) {
+ // TEMP: allocate with malloc. in the future we will have a pool allocator on the context
+ gpu_renderpass* renderpass = malloc(sizeof(gpu_renderpass));
+
+ // Colour attachment
+ VkAttachmentDescription color_attachment;
+ // color_attachment.format = context->swapchain.image_format.format;
+ color_attachment.samples = VK_SAMPLE_COUNT_1_BIT;
+ color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ color_attachment.flags = 0;
+
+ // attachment_descriptions[0] = color_attachment;
+
+ VkAttachmentReference color_attachment_reference;
+ color_attachment_reference.attachment = 0;
+ color_attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ // subpass.colorAttachmentCount = 1;
+ // subpass.pColorAttachments = &color_attachment_reference;
+
+ // TODO: Depth attachment
+
+ // main subpass
+ VkSubpassDescription subpass = { 0 };
+ subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpass.colorAttachmentCount = 1;
+ subpass.pColorAttachments = &color_attachment_reference;
+
// sets everything up
- // return pointer to it
+
+ // Finally, create the RenderPass
+ VkRenderPassCreateInfo render_pass_create_info = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
+
+ return renderpass;
}
void encode_set_pipeline(gpu_cmd_encoder* encoder, gpu_pipeline* pipeline) {
diff --git a/src/renderer/backends/backend_vulkan.h b/src/renderer/backends/backend_vulkan.h
index dfe6a0f..9802311 100644
--- a/src/renderer/backends/backend_vulkan.h
+++ b/src/renderer/backends/backend_vulkan.h
@@ -4,6 +4,7 @@
#include <vulkan/vulkan_core.h>
#include "defines.h"
+#include "ral.h"
#define GPU_SWAPCHAIN_IMG_COUNT 2
@@ -16,6 +17,7 @@ Conventions:
typedef struct gpu_swapchain {
VkSwapchainKHR handle;
} gpu_swapchain;
+
typedef struct gpu_device {
// In Vulkan we store both physical and logical device here
VkPhysicalDevice physical_device;
@@ -25,11 +27,18 @@ typedef struct gpu_device {
VkPhysicalDeviceMemoryProperties memory;
VkCommandPool pool;
} gpu_device;
+
+typedef struct gpu_pipeline_layout {
+ VkPipelineLayout handle;
+} gpu_pipeline_layout;
+
typedef struct gpu_pipeline {
+ VkPipeline handle;
+ VkPipelineLayout layout_handle;
} gpu_pipeline;
typedef struct gpu_renderpass {
- VkRenderPass vk_handle;
+ VkRenderPass handle;
VkFramebuffer framebuffers[GPU_SWAPCHAIN_IMG_COUNT];
} gpu_renderpass;
diff --git a/src/renderer/backends/vulkan_helpers.h b/src/renderer/backends/vulkan_helpers.h
index 3465aed..4bd02f1 100644
--- a/src/renderer/backends/vulkan_helpers.h
+++ b/src/renderer/backends/vulkan_helpers.h
@@ -21,7 +21,12 @@ static void plat_get_required_extension_names(cstr_darray* extensions) {
// TODO(omni): port to using internal assert functions
#define VK_CHECK(vulkan_expr) \
- { assert(vulkan_expr == VK_SUCCESS); }
+ do { \
+ VkResult res = vulkan_expr; \
+ if (res != VK_SUCCESS) { \
+ ERROR_EXIT("Vulkan error: %u", res); \
+ } \
+ } while (0)
// TODO: typedef struct vk_debugger {} vk_debugger;
diff --git a/src/renderer/bind_group_layouts.h b/src/renderer/bind_group_layouts.h
new file mode 100644
index 0000000..d163fab
--- /dev/null
+++ b/src/renderer/bind_group_layouts.h
@@ -0,0 +1,30 @@
+/**
+ * @file bind_group_layouts.h
+ * @author your name (you@domain.com)
+ * @brief Common bindgroups (descriptor set layouts)
+ * @version 0.1
+ * @date 2024-04-28
+ *
+ * @copyright Copyright (c) 2024
+ *
+ */
+#pragma once
+#include "defines.h"
+#include "maths_types.h"
+
+// Three major sets
+
+// 1. Scene / Global
+typedef struct bg_globals {
+ f32 total_time;
+ f32 delta_time;
+ mat4 view;
+ mat4 projection;
+} bg_globals;
+
+// 2. Material (once per object)
+
+// 3. Per draw call
+typedef struct bg_model {
+ mat4 model;
+} bg_model;
diff --git a/src/renderer/ral.h b/src/renderer/ral.h
index 6c165c9..8e49dbe 100644
--- a/src/renderer/ral.h
+++ b/src/renderer/ral.h
@@ -23,11 +23,20 @@ struct GLFWwindow;
// Forward declare structs
typedef struct gpu_swapchain gpu_swapchain;
typedef struct gpu_device gpu_device;
+typedef struct gpu_pipeline_layout gpu_pipeline_layout;
typedef struct gpu_pipeline gpu_pipeline;
typedef struct gpu_renderpass gpu_renderpass;
typedef struct gpu_cmd_encoder gpu_cmd_encoder; // Recording
typedef struct gpu_cmd_buffer gpu_cmd_buffer; // Ready for submission
+/** @brief A*/
+// typedef struct gpu_bind_group
+
+// Pools
+typedef struct gpu_backend_pools {
+ // pools for each gpu structure
+} gpu_backend_pools;
+
typedef enum pipeline_kind {
PIPELINE_GRAPHICS,
PIPELINE_COMPUTE,
@@ -40,10 +49,20 @@ typedef struct shader_desc {
} shader_desc;
struct graphics_pipeline_desc {
+ const char* debug_name;
shader_desc vs; /** @brief Vertex shader stage */
shader_desc fs; /** @brief Fragment shader stage */
+ // gpu_pipeline_layout* layout;
+ gpu_renderpass* renderpass;
+
+ bool wireframe;
+ bool depth_test;
};
+typedef struct gpu_renderpass_desc {
+
+} gpu_renderpass_desc;
+
// --- Lifecycle functions
bool gpu_backend_init(const char* window_name, struct GLFWwindow* window);
@@ -52,7 +71,7 @@ void gpu_backend_shutdown();
bool gpu_device_create(gpu_device* out_device);
void gpu_device_destroy();
-gpu_renderpass* gpu_renderpass_create();
+gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description);
void gpu_renderpass_destroy(gpu_renderpass* pass);
gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description);
@@ -75,6 +94,7 @@ void encode_set_pipeline(gpu_cmd_encoder* encoder, gpu_pipeline* pipeline);
void buffer_upload_bytes(buffer_handle gpu_buf, bytebuffer cpu_buf, u64 offset, u64 size);
// render pass
+void encode_bind_pipeline(gpu_cmd_encoder* encoder, pipeline_kind kind, gpu_pipeline* pipeline);
void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf);
void encode_set_index_buffer(gpu_cmd_encoder* encoder, buffer_handle buf);
void encode_set_bind_group(); // TODO
diff --git a/src/renderer/ral_types.h b/src/renderer/ral_types.h
index 5f41b55..0b1c02e 100644
--- a/src/renderer/ral_types.h
+++ b/src/renderer/ral_types.h
@@ -99,6 +99,12 @@ KITC_DECL_TYPED_ARRAY(u32)
#define TYPED_VERTEX_ARRAY
#endif
+typedef enum gpu_cull_mode {
+ CULL_BACK_FACE,
+ CULL_FRONT_FACE,
+ CULL_COUNT
+} gpu_cull_mode;
+
// ? How to tie together materials and shaders
// Three registers
diff --git a/src/renderer/render.h b/src/renderer/render.h
index a5a5928..a9370e0 100644
--- a/src/renderer/render.h
+++ b/src/renderer/render.h
@@ -17,6 +17,7 @@ bool renderer_init(renderer* ren);
void renderer_shutdown(renderer* ren);
void render_frame_begin(renderer* ren);
+void render_frame_update_globals(renderer* ren);
void render_frame_end(renderer* ren);
void render_frame_draw(renderer* ren);
diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h
index 6ef2461..4866ef4 100644
--- a/src/renderer/render_types.h
+++ b/src/renderer/render_types.h
@@ -13,7 +13,8 @@
#include "ral_types.h"
#include "ral.h"
#if defined(CEL_PLATFORM_WINDOWS)
-#include "backend_dx11.h"
+// #include "backend_dx11.h"
+#include "backend_vulkan.h"
#endif
struct GLFWwindow;
@@ -36,7 +37,7 @@ typedef struct renderer {
typedef struct geometry_data {
vertex_format format;
- vertex_darray* vertices; // TODO: make it not a pointe
+ vertex_darray* vertices; // TODO: make it not a pointer
bool has_indices;
u32_darray indices;
vec3 colour; /** Optional: set vertex colours */
diff --git a/src/renderer/renderpasses.h b/src/renderer/renderpasses.h
new file mode 100644
index 0000000..67badaa
--- /dev/null
+++ b/src/renderer/renderpasses.h
@@ -0,0 +1,31 @@
+/**
+ * @file renderpasses.h
+ * @author your name (you@domain.com)
+ * @brief Built-in renderpasses to the engine
+ * @version 0.1
+ * @date 2024-04-28
+ *
+ * @copyright Copyright (c) 2024
+ *
+ */
+#pragma once
+#include "maths_types.h"
+#include "ral.h"
+#include "render.h"
+
+// Shadowmap pass
+// Blinn-phong pass
+// Unlit pass
+// Debug visualisations pass
+
+typedef struct render_entity {
+ model* model;
+ transform tf;
+} render_entity;
+
+// Don't need to pass in *anything*.
+gpu_renderpass* renderpass_blinn_phong_create();
+void renderpass_blinn_phong_execute(gpu_renderpass* pass, render_entity* entities, size_t entity_count);
+
+gpu_renderpass* renderpass_shadows_create();
+void renderpass_shadows_execute(gpu_renderpass* pass, render_entity* entities, size_t entity_count); \ No newline at end of file