summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rwxr-xr-xshaders/compile.sh3
-rw-r--r--shaders/triangle.frag8
-rw-r--r--shaders/triangle.vert20
-rw-r--r--src/main.c98
5 files changed, 130 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index bc95448..8dda78e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
.cache/
build/
+shaders/*.spv
diff --git a/shaders/compile.sh b/shaders/compile.sh
new file mode 100755
index 0000000..b60f97c
--- /dev/null
+++ b/shaders/compile.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+glslc triangle.vert -o triangle.vert.spv
+glslc triangle.frag -o triangle.frag.spv
diff --git a/shaders/triangle.frag b/shaders/triangle.frag
new file mode 100644
index 0000000..75d5fcd
--- /dev/null
+++ b/shaders/triangle.frag
@@ -0,0 +1,8 @@
+#version 450
+
+layout(location = 0) in vec3 frag_color;
+layout(location = 0) out vec4 out_color;
+
+void main() {
+ out_color = vec4(frag_color, 1.0);
+}
diff --git a/shaders/triangle.vert b/shaders/triangle.vert
new file mode 100644
index 0000000..9f35e1a
--- /dev/null
+++ b/shaders/triangle.vert
@@ -0,0 +1,20 @@
+#version 450
+
+vec2 positions[3] = vec2[](
+ vec2(0.0, -0.5),
+ vec2(0.5, 0.5),
+ vec2(-0.5, 0.5)
+);
+
+vec3 colors[3] = vec3[](
+ vec3(1.0, 0.0, 0.0),
+ vec3(0.0, 1.0, 0.0),
+ vec3(0.0, 0.0, 1.0)
+);
+
+layout(location = 0) out vec3 frag_color;
+
+void main() {
+ gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
+ frag_color = colors[gl_VertexIndex];
+}
diff --git a/src/main.c b/src/main.c
index 32b9d64..65cf0f7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -612,6 +612,91 @@ err:
return false;
}
+char *load_shader_from_file(const char *path, size_t *out_size) {
+ FILE *file_handle = fopen(path, "rb");
+ if (!file_handle) {
+ goto err;
+ }
+
+ if (fseek(file_handle, 0, SEEK_END) < 0) {
+ goto close_file;
+ }
+
+ long file_size = ftell(file_handle);
+ if (file_size < 0) {
+ goto close_file;
+ }
+ rewind(file_handle);
+ char *shader_file_content = malloc(file_size);
+ if (fread(shader_file_content, file_size, 1, file_handle) != 1) {
+ goto free_shader_file_content;
+ }
+
+ if (fclose(file_handle) != 0) {
+ goto err;
+ }
+
+ *out_size = file_size;
+ return shader_file_content;
+free_shader_file_content:
+ free(shader_file_content);
+close_file:
+ fclose(file_handle);
+err:
+ return NULL;
+}
+
+VkShaderModule create_shader_module(VkDevice device, char *code,
+ size_t code_size) {
+ VkShaderModule shader_module;
+ if (vkCreateShaderModule(
+ device,
+ &(const VkShaderModuleCreateInfo){
+ .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+ .codeSize = code_size,
+ .pCode = (const uint32_t *)code,
+ },
+ NULL, &shader_module) != VK_SUCCESS) {
+ return NULL;
+ }
+
+ return shader_module;
+}
+
+bool vulkan_renderer_create_graphics_pipeline(
+ struct vulkan_renderer *renderer) {
+ size_t vertex_shader_code_size;
+ char *vertex_shader_code = load_shader_from_file("shaders/triangle.vert.spv",
+ &vertex_shader_code_size);
+ size_t fragment_shader_code_size;
+ char *fragment_shader_code = load_shader_from_file(
+ "shaders/triangle.frag.spv", &fragment_shader_code_size);
+ VkShaderModule vertex_shader_module = create_shader_module(
+ renderer->device, vertex_shader_code, vertex_shader_code_size);
+ VkShaderModule fragment_shader_module = create_shader_module(
+ renderer->device, fragment_shader_code, fragment_shader_code_size);
+ free(vertex_shader_code);
+ free(fragment_shader_code);
+
+ VkPipelineShaderStageCreateInfo vertex_shader_stage_info = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ .stage = VK_SHADER_STAGE_VERTEX_BIT,
+ .module = vertex_shader_module,
+ .pName = "main"};
+ VkPipelineShaderStageCreateInfo fragment_shader_stage_info = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
+ .module = fragment_shader_module,
+ .pName = "main"};
+
+ VkPipelineShaderStageCreateInfo shader_stages[] = {
+ vertex_shader_stage_info, fragment_shader_stage_info};
+
+ vkDestroyShaderModule(renderer->device, vertex_shader_module, NULL);
+ vkDestroyShaderModule(renderer->device, fragment_shader_module, NULL);
+ return true;
+}
+
bool vulkan_renderer_init(struct vulkan_renderer *renderer,
SDL_Window *window) {
assert(renderer);
@@ -666,8 +751,21 @@ bool vulkan_renderer_init(struct vulkan_renderer *renderer,
goto destroy_swapchain;
}
+ if (!vulkan_renderer_create_graphics_pipeline(renderer)) {
+ LOG("Couldn't create graphics pipeline");
+ goto destroy_swapchain_image_views;
+ }
+
return true;
+destroy_swapchain_image_views:
+ for (uint32_t swapchain_image_view_index = 0;
+ swapchain_image_view_index < renderer->swapchain_image_count;
+ swapchain_image_view_index++) {
+ vkDestroyImageView(
+ renderer->device,
+ renderer->swapchain_image_views[swapchain_image_view_index], NULL);
+ }
destroy_swapchain:
vkDestroySwapchainKHR(renderer->device, renderer->swapchain, NULL);
destroy_logical_device:
Go back to lisible.xyz