summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--shaders/triangle.frag9
-rw-r--r--shaders/triangle.vert20
-rw-r--r--src/renderer.c214
-rw-r--r--src/renderer.h3
5 files changed, 247 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index ceddaa3..2afcec9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
.cache/
+compiled_shaders/
diff --git a/shaders/triangle.frag b/shaders/triangle.frag
new file mode 100644
index 0000000..7c5b0e7
--- /dev/null
+++ b/shaders/triangle.frag
@@ -0,0 +1,9 @@
+#version 450
+
+layout(location = 0) in vec3 fragColor;
+
+layout(location = 0) out vec4 outColor;
+
+void main() {
+ outColor = vec4(fragColor, 1.0);
+}
diff --git a/shaders/triangle.vert b/shaders/triangle.vert
new file mode 100644
index 0000000..f5b2f8d
--- /dev/null
+++ b/shaders/triangle.vert
@@ -0,0 +1,20 @@
+#version 450
+
+layout(location = 0) out vec3 fragColor;
+
+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)
+);
+
+void main() {
+ gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
+ fragColor = colors[gl_VertexIndex];
+}
diff --git a/src/renderer.c b/src/renderer.c
index cacd3bd..f04fea9 100644
--- a/src/renderer.c
+++ b/src/renderer.c
@@ -862,6 +862,197 @@ err:
return false;
}
+static bool create_shader_module(VkDevice device, const unsigned char *code,
+ int size, VkShaderModule *out) {
+ VkShaderModuleCreateInfo create_info = {
+ .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+ .codeSize = size,
+ .pCode = (const uint32_t *)code,
+ };
+ if (vkCreateShaderModule(device, &create_info, nullptr, out) != VK_SUCCESS) {
+ VGLTF_LOG_ERR("Couldn't create shader module");
+ goto err;
+ }
+ return true;
+err:
+ return false;
+}
+
+static bool vgltf_renderer_create_render_pass(struct vgltf_renderer *renderer) {
+ VkAttachmentDescription color_attachment = {
+ .format = renderer->swapchain_image_format,
+ .samples = VK_SAMPLE_COUNT_1_BIT,
+ .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
+ .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
+ .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
+ .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR};
+ VkAttachmentReference color_attachment_ref = {
+ .attachment = 0,
+ .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ };
+ VkSubpassDescription subpass = {.pipelineBindPoint =
+ VK_PIPELINE_BIND_POINT_GRAPHICS,
+ .pColorAttachments = &color_attachment_ref};
+ VkRenderPassCreateInfo render_pass_info = {
+ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ .attachmentCount = 1,
+ .pAttachments = &color_attachment,
+ .subpassCount = 1,
+ .pSubpasses = &subpass};
+
+ if (vkCreateRenderPass(renderer->device, &render_pass_info, nullptr,
+ &renderer->render_pass) != VK_SUCCESS) {
+ VGLTF_LOG_ERR("Failed to create render pass");
+ goto err;
+ }
+
+ return true;
+err:
+ return false;
+}
+
+static bool
+vgltf_renderer_create_graphics_pipeline(struct vgltf_renderer *renderer) {
+ static constexpr unsigned char triangle_shader_vert_code[] = {
+#embed "../compiled_shaders/triangle.vert.spv"
+ };
+ static constexpr unsigned char triangle_shader_frag_code[] = {
+#embed "../compiled_shaders/triangle.frag.spv"
+ };
+
+ VkShaderModule triangle_shader_vert_module;
+ if (!create_shader_module(renderer->device, triangle_shader_vert_code,
+ sizeof(triangle_shader_vert_code),
+ &triangle_shader_vert_module)) {
+ VGLTF_LOG_ERR("Couldn't create triangle vert shader module");
+ goto err;
+ }
+
+ VkShaderModule triangle_shader_frag_module;
+ if (!create_shader_module(renderer->device, triangle_shader_frag_code,
+ sizeof(triangle_shader_frag_code),
+ &triangle_shader_frag_module)) {
+ VGLTF_LOG_ERR("Couldn't create triangle frag shader module");
+ goto destroy_vert_shader_module;
+ }
+
+ VkPipelineShaderStageCreateInfo triangle_shader_vert_stage_create_info = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ .stage = VK_SHADER_STAGE_VERTEX_BIT,
+ .module = triangle_shader_vert_module,
+ .pName = "main"};
+ VkPipelineShaderStageCreateInfo triangle_shader_frag_stage_create_info = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
+ .module = triangle_shader_frag_module,
+ .pName = "main"};
+ VkPipelineShaderStageCreateInfo shader_stages[] = {
+ triangle_shader_vert_stage_create_info,
+ triangle_shader_frag_stage_create_info};
+
+ VkDynamicState dynamic_states[] = {
+ VK_DYNAMIC_STATE_VIEWPORT,
+ VK_DYNAMIC_STATE_SCISSOR,
+ };
+
+ VkPipelineDynamicStateCreateInfo dynamic_state = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
+ .dynamicStateCount = sizeof(dynamic_states) / sizeof(dynamic_states[0]),
+ .pDynamicStates = dynamic_states};
+
+ VkPipelineVertexInputStateCreateInfo vertex_input_info = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+ .vertexBindingDescriptionCount = 0,
+ .vertexAttributeDescriptionCount = 0,
+ };
+
+ VkPipelineInputAssemblyStateCreateInfo input_assembly = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
+ .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
+ .primitiveRestartEnable = VK_FALSE,
+ };
+
+ VkPipelineViewportStateCreateInfo viewport_state = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
+ .viewportCount = 1,
+ .scissorCount = 1};
+
+ VkPipelineRasterizationStateCreateInfo rasterizer = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
+ .depthClampEnable = VK_FALSE,
+ .rasterizerDiscardEnable = VK_FALSE,
+ .polygonMode = VK_POLYGON_MODE_FILL,
+ .lineWidth = 1.f,
+ .cullMode = VK_CULL_MODE_BACK_BIT,
+ .frontFace = VK_FRONT_FACE_CLOCKWISE,
+ .depthBiasEnable = VK_FALSE};
+
+ VkPipelineMultisampleStateCreateInfo multisampling = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
+ .sampleShadingEnable = VK_FALSE,
+ .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
+ };
+
+ VkPipelineColorBlendAttachmentState color_blend_attachment = {
+ .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
+ VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
+ .blendEnable = VK_FALSE,
+ };
+
+ VkPipelineColorBlendStateCreateInfo color_blending = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
+ .logicOpEnable = VK_FALSE,
+ .attachmentCount = 1,
+ .pAttachments = &color_blend_attachment};
+
+ VkPipelineLayoutCreateInfo pipeline_layout_info = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ };
+
+ if (vkCreatePipelineLayout(renderer->device, &pipeline_layout_info, nullptr,
+ &renderer->pipeline_layout) != VK_SUCCESS) {
+ VGLTF_LOG_ERR("Couldn't create pipeline layout");
+ goto destroy_frag_shader_module;
+ }
+
+ VkGraphicsPipelineCreateInfo pipeline_info = {
+ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+ .stageCount = 2,
+ .pStages = shader_stages,
+ .pVertexInputState = &vertex_input_info,
+ .pInputAssemblyState = &input_assembly,
+ .pViewportState = &viewport_state,
+ .pRasterizationState = &rasterizer,
+ .pMultisampleState = &multisampling,
+ .pColorBlendState = &color_blending,
+ .pDynamicState = &dynamic_state,
+ .layout = renderer->pipeline_layout,
+ .renderPass = renderer->render_pass,
+ .subpass = 0,
+ };
+
+ if (vkCreateGraphicsPipelines(renderer->device, VK_NULL_HANDLE, 1,
+ &pipeline_info, nullptr,
+ &renderer->graphics_pipeline) != VK_SUCCESS) {
+ VGLTF_LOG_ERR("Couldn't create pipeline");
+ goto destroy_pipeline_layout;
+ }
+
+ vkDestroyShaderModule(renderer->device, triangle_shader_frag_module, nullptr);
+ vkDestroyShaderModule(renderer->device, triangle_shader_vert_module, nullptr);
+ return true;
+destroy_pipeline_layout:
+ vkDestroyPipelineLayout(renderer->device, renderer->pipeline_layout, nullptr);
+destroy_frag_shader_module:
+ vkDestroyShaderModule(renderer->device, triangle_shader_frag_module, nullptr);
+destroy_vert_shader_module:
+ vkDestroyShaderModule(renderer->device, triangle_shader_vert_module, nullptr);
+err:
+ return false;
+}
+
bool vgltf_renderer_init(struct vgltf_renderer *renderer,
struct vgltf_platform *platform) {
if (!vgltf_renderer_create_instance(renderer, platform)) {
@@ -899,7 +1090,27 @@ bool vgltf_renderer_init(struct vgltf_renderer *renderer,
goto destroy_swapchain;
}
+ if (!vgltf_renderer_create_render_pass(renderer)) {
+ VGLTF_LOG_ERR("Couldn't create render pass");
+ goto destroy_image_views;
+ }
+
+ if (!vgltf_renderer_create_graphics_pipeline(renderer)) {
+ VGLTF_LOG_ERR("Couldn't create graphics pipeline");
+ goto destroy_render_pass;
+ }
+
return true;
+destroy_render_pass:
+ vkDestroyRenderPass(renderer->device, renderer->render_pass, nullptr);
+destroy_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], nullptr);
+ }
destroy_swapchain:
vkDestroySwapchainKHR(renderer->device, renderer->swapchain, nullptr);
destroy_device:
@@ -916,6 +1127,9 @@ err:
return false;
}
void vgltf_renderer_deinit(struct vgltf_renderer *renderer) {
+ vkDestroyPipeline(renderer->device, renderer->graphics_pipeline, nullptr);
+ vkDestroyPipelineLayout(renderer->device, renderer->pipeline_layout, nullptr);
+ vkDestroyRenderPass(renderer->device, renderer->render_pass, nullptr);
for (uint32_t swapchain_image_view_index = 0;
swapchain_image_view_index < renderer->swapchain_image_count;
swapchain_image_view_index++) {
diff --git a/src/renderer.h b/src/renderer.h
index 5e08762..3a7dbad 100644
--- a/src/renderer.h
+++ b/src/renderer.h
@@ -19,6 +19,9 @@ struct vgltf_renderer {
VkFormat swapchain_image_format;
VkExtent2D swapchain_extent;
uint32_t swapchain_image_count;
+ VkRenderPass render_pass;
+ VkPipelineLayout pipeline_layout;
+ VkPipeline graphics_pipeline;
};
bool vgltf_renderer_init(struct vgltf_renderer *renderer,
struct vgltf_platform *platform);
Go back to lisible.xyz