From bed890892f8ecd549524b1f58878e66fe429158d Mon Sep 17 00:00:00 2001 From: Clément Sibille Date: Wed, 19 Mar 2025 07:59:51 +0100 Subject: Add render pipeline creation --- src/renderer.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/renderer.h | 3 + 2 files changed, 217 insertions(+) (limited to 'src') 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); -- cgit v1.2.3