#include "VulkanManager.h" #define CHECK_RESULT(res) if (res != VK_SUCCESS) { return res; } namespace PB::Renderer { bool VulkanManager::RenderPass(GLFWwindow* window) { switch (const VkResult result = RenderPassInternal()) { case VK_ERROR_OUT_OF_DATE_KHR: case VK_SUBOPTIMAL_KHR: RecreateSwapChain(window); return true; default: return result == VK_SUCCESS; } } void VulkanManager::RecreateSwapChain(GLFWwindow* window) { int width, height; glfwGetFramebufferSize(window, &width, &height); /* Pauses if minimised */ while (width == 0 || height == 0) { glfwGetFramebufferSize(window, &width, &height); glfwWaitEvents(); } /* Waits until device is idle before recreating swap chain */ vkDeviceWaitIdle(s_Device); CleanupSwapChain(); CreateSwapChain(window); CreateImageViews(); CreateRenderPass(); CreateFramebuffer(); CreateGraphicsPipeline(); CreateCommandBuffers(); CreateSemaphores(); } void VulkanManager::CleanupSwapChain() { for (const VkFramebuffer framebuffer : s_Framebuffers) { vkDestroyFramebuffer(s_Device, framebuffer, nullptr); } s_Framebuffers.clear(); vkFreeCommandBuffers(s_Device, s_CommandPool, static_cast(s_CommandBuffers.size()), s_CommandBuffers.data()); vkDestroyPipeline(s_Device, s_RenderPipeline, nullptr); vkDestroyPipelineLayout(s_Device, s_PipelineLayout, nullptr); vkDestroyRenderPass(s_Device, s_RenderPass, nullptr); for (const VkImageView view : s_SwapChainImageViews) { vkDestroyImageView(s_Device, view, nullptr); } vkDestroySwapchainKHR(s_Device, s_SwapChain, nullptr); } VkResult VulkanManager::RenderPassInternal() { uint32_t imageIndex; VkResult result = vkAcquireNextImageKHR( s_Device, s_SwapChain, UINT64_MAX, s_ImageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex ); CHECK_RESULT(result); VkSubmitInfo submitInfo{}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; const VkSemaphore waitSemaphores[] = { s_ImageAvailableSemaphore }; constexpr VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitDstStageMask = waitStages; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &s_CommandBuffers[imageIndex]; const VkSemaphore signalSemaphores[] = { s_RenderFinishedSemaphore }; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signalSemaphores; result = vkQueueSubmit(s_GraphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); CHECK_RESULT(result); VkPresentInfoKHR presentInfo{}; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.waitSemaphoreCount = 1; presentInfo.pWaitSemaphores = signalSemaphores; const VkSwapchainKHR swapChains[] = { s_SwapChain }; presentInfo.swapchainCount = 1; presentInfo.pSwapchains = swapChains; presentInfo.pImageIndices = &imageIndex; result = vkQueuePresentKHR(s_PresentQueue, &presentInfo); CHECK_RESULT(result); vkQueueWaitIdle(s_PresentQueue); return VK_SUCCESS; } }