From 8024a6d59a4595f69f03466b66f4ea2eea87fcf9 Mon Sep 17 00:00:00 2001 From: vimene Date: Sat, 20 Dec 2025 00:24:06 +0100 Subject: added rendering and presentation --- src/engine.cpp | 247 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 172 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/engine.cpp b/src/engine.cpp index 1ade915..31f72d0 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -784,6 +784,7 @@ static int main_graphical() { VkPhysicalDeviceVulkan13Features device_vk13_features{}; device_vk13_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; + device_vk13_features.synchronization2 = VK_TRUE; device_vk13_features.dynamicRendering = VK_TRUE; device_features.pNext = &device_vk13_features; @@ -1166,89 +1167,185 @@ static int main_graphical() { std::exit(EXIT_FAILURE); } + // create sync objects + VkSemaphore sem_present_complete, sem_render_finished; + VkFence fence_draw; + + // TODO: I don't know if I have to use 2 different VkSemaphoreCreateInfo, but for now, let's do + // this so we're sure it'll work + VkSemaphoreCreateInfo sem_present_complete_ci { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + .pNext = nullptr, + .flags = {}, + }; + if (VkResult res = vkCreateSemaphore(logical_device, &sem_present_complete_ci, nullptr, &sem_present_complete); res != VK_SUCCESS) { + std::cerr << "failed to create present complete semaphore, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + std::cout << "sem_present_complete: " << sem_present_complete << std::endl; + VkSemaphoreCreateInfo sem_render_finished_ci { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + .pNext = nullptr, + .flags = {}, + }; + if (VkResult res = vkCreateSemaphore(logical_device, &sem_render_finished_ci, nullptr, &sem_render_finished); res != VK_SUCCESS) { + std::cerr << "failed to create render finished semaphore, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + std::cout << "sem_render_finished: " << sem_render_finished << std::endl; + + VkFenceCreateInfo fence_draw_ci { + .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, + .pNext = nullptr, + .flags = VK_FENCE_CREATE_SIGNALED_BIT, + }; + if (VkResult res = vkCreateFence(logical_device, &fence_draw_ci, nullptr, &fence_draw); res != VK_SUCCESS) { + std::cerr << "failed to create draw semaphore, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + std::cout << "fence_draw: " << fence_draw << std::endl; + // main loop while (!glfwWindowShouldClose(window)) { glfwPollEvents(); - // this shouldn't be a function, it has to be removed (but keep the inside) once it can run. - // Keeping it like this gives the opportunity to check for simple errors while it can't run - [&]() { - uint32_t img_idx {}; // TODO: define properly - VkCommandBufferBeginInfo cmd_buf_bi { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - .pNext = nullptr, - .flags = {}, - .pInheritanceInfo = {}, - }; - if (VkResult res = vkBeginCommandBuffer(cmd_buf, &cmd_buf_bi); res != VK_SUCCESS) { - std::cerr << "failed to begin command buffer, error code: " << string_VkResult(res) << std::endl; - std::exit(EXIT_FAILURE); - } - transition_image_layout(cmd_buf, swapchain_imgs[img_idx], - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - {}, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, - VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT); - VkClearValue clear_val { .color = { .float32 = { 0.f, 0.f, 0.f, 1.f } }, }; - VkRenderingAttachmentInfo attachment_info { - .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, - .pNext = nullptr, - .imageView = swapchain_img_views[img_idx], - .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - .resolveMode = {}, - .resolveImageView = {}, - .resolveImageLayout = {}, - .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .clearValue = clear_val, - }; - VkRenderingInfo render_info { - .sType = VK_STRUCTURE_TYPE_RENDERING_INFO, - .pNext = nullptr, - .flags = {}, - .renderArea = { .offset { 0, 0 }, .extent = swapchain_extent }, - .layerCount = 1, - .viewMask = {}, - .colorAttachmentCount = 1, - .pColorAttachments = &attachment_info, - .pDepthAttachment = {}, - .pStencilAttachment = {}, - }; - vkCmdBeginRendering(cmd_buf, &render_info); - vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pl); - - VkViewport viewport { - .x = 0.f, - .y = 0.f, - .width = static_cast(swapchain_extent.width), - .height = static_cast(swapchain_extent.height), - .minDepth = 0.f, - .maxDepth = 1.f, - }; - vkCmdSetViewport(cmd_buf, 0, 1, &viewport); - - VkRect2D scissor { - .offset = { 0, 0 }, - .extent = swapchain_extent, - }; - vkCmdSetScissor(cmd_buf, 0, 1, &scissor); - - vkCmdDraw(cmd_buf, 3, 1, 0, 0); - - vkCmdEndRendering(cmd_buf); - - transition_image_layout(cmd_buf, swapchain_imgs[img_idx], - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, {}, - VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT); - - if (VkResult res = vkEndCommandBuffer(cmd_buf); res != VK_SUCCESS) { - std::cerr << "failed to end command buffer, error code: " << string_VkResult(res) << std::endl; - std::exit(EXIT_FAILURE); - } + if (VkResult res = vkQueueWaitIdle(graphics_queue); res != VK_SUCCESS) { + std::cerr << "failed to wait idle for graphics queue, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + + uint32_t img_idx; + if (VkResult res = vkAcquireNextImageKHR(logical_device, swapchain, + std::numeric_limits::max(), sem_present_complete, nullptr, &img_idx); res != VK_SUCCESS) { + std::cerr << "failed to acquire next image, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + + // record command buffer + VkCommandBufferBeginInfo cmd_buf_bi { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .pNext = nullptr, + .flags = {}, + .pInheritanceInfo = {}, + }; + if (VkResult res = vkBeginCommandBuffer(cmd_buf, &cmd_buf_bi); res != VK_SUCCESS) { + std::cerr << "failed to begin command buffer, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + transition_image_layout(cmd_buf, swapchain_imgs[img_idx], + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + {}, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, + VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT); + VkClearValue clear_val { .color = { .float32 = { 0.f, 0.f, 0.f, 1.f } }, }; + VkRenderingAttachmentInfo attachment_info { + .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, + .pNext = nullptr, + .imageView = swapchain_img_views[img_idx], + .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + .resolveMode = {}, + .resolveImageView = {}, + .resolveImageLayout = {}, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .clearValue = clear_val, + }; + VkRenderingInfo render_info { + .sType = VK_STRUCTURE_TYPE_RENDERING_INFO, + .pNext = nullptr, + .flags = {}, + .renderArea = { .offset { 0, 0 }, .extent = swapchain_extent }, + .layerCount = 1, + .viewMask = {}, + .colorAttachmentCount = 1, + .pColorAttachments = &attachment_info, + .pDepthAttachment = {}, + .pStencilAttachment = {}, }; + vkCmdBeginRendering(cmd_buf, &render_info); + vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pl); + + VkViewport viewport { + .x = 0.f, + .y = 0.f, + .width = static_cast(swapchain_extent.width), + .height = static_cast(swapchain_extent.height), + .minDepth = 0.f, + .maxDepth = 1.f, + }; + vkCmdSetViewport(cmd_buf, 0, 1, &viewport); + + VkRect2D scissor { + .offset = { 0, 0 }, + .extent = swapchain_extent, + }; + vkCmdSetScissor(cmd_buf, 0, 1, &scissor); + + vkCmdDraw(cmd_buf, 3, 1, 0, 0); + + vkCmdEndRendering(cmd_buf); + + transition_image_layout(cmd_buf, swapchain_imgs[img_idx], + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, {}, + VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT); + + if (VkResult res = vkEndCommandBuffer(cmd_buf); res != VK_SUCCESS) { + std::cerr << "failed to end command buffer, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + + if (VkResult res = vkResetFences(logical_device, 1, &fence_draw); res != VK_SUCCESS) { + std::cerr << "failed to reset draw fence, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + + VkPipelineStageFlags pl_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkSubmitInfo submit_info { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pNext = nullptr, + .waitSemaphoreCount = 1, + .pWaitSemaphores = &sem_present_complete, + .pWaitDstStageMask = &pl_stage_flags, + .commandBufferCount = 1, + .pCommandBuffers = &cmd_buf, + .signalSemaphoreCount = 1, + .pSignalSemaphores = &sem_render_finished, + }; + if (VkResult res = vkQueueSubmit(graphics_queue, 1, &submit_info, fence_draw); res != VK_SUCCESS) { + std::cerr << "failed to submit queue, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + + if (VkResult res = vkWaitForFences(logical_device, 1, &fence_draw, VK_TRUE, std::numeric_limits::max()); res != VK_SUCCESS) { + std::cerr << "failed to wait for draw fence, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + + VkPresentInfoKHR present_info { + .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + .pNext = nullptr, + .waitSemaphoreCount = 1, + .pWaitSemaphores = &sem_render_finished, + .swapchainCount = 1, + .pSwapchains = &swapchain, + .pImageIndices = &img_idx, + .pResults = nullptr, + }; + if (VkResult res = vkQueuePresentKHR(presentation_queue, &present_info); res != VK_SUCCESS) { + std::cerr << "failed to present, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); + } + } + + if (VkResult res = vkDeviceWaitIdle(logical_device); res != VK_SUCCESS) { + std::cerr << "failed to wait idle for device, error code: " << string_VkResult(res) << std::endl; + std::exit(EXIT_FAILURE); } // cleanup + vkDestroyFence(logical_device, fence_draw, nullptr); + vkDestroySemaphore(logical_device, sem_render_finished, nullptr); + vkDestroySemaphore(logical_device, sem_present_complete, nullptr); vkDestroyCommandPool(logical_device, cmd_pool, nullptr); vkDestroyPipeline(logical_device, graphics_pl, nullptr); vkDestroyPipelineLayout(logical_device, pl_layout, nullptr); -- cgit v1.2.3