diff --git a/kraken/KRPresentationThread.cpp b/kraken/KRPresentationThread.cpp index f79c3ac..b81c434 100644 --- a/kraken/KRPresentationThread.cpp +++ b/kraken/KRPresentationThread.cpp @@ -71,15 +71,24 @@ void KRPresentationThread::run() m_activeState = PresentThreadState::run; while (m_requestedState != PresentThreadRequest::stop) { - while (m_requestedState == PresentThreadRequest::run) { - m_activeState = PresentThreadState::run; - renderFrame(); - std::this_thread::sleep_for(sleep_duration); - } - while (m_requestedState == PresentThreadRequest::pause) { - m_activeState = PresentThreadState::pause; - std::this_thread::sleep_for(sleep_duration); + switch (m_activeState) { + case PresentThreadState::pause: + case PresentThreadState::stop: + if (m_requestedState == PresentThreadRequest::run) { + m_activeState = PresentThreadState::run; + } + break; + case PresentThreadState::run: + if (m_requestedState == PresentThreadRequest::pause) { + m_activeState = PresentThreadState::pause; + } else { + renderFrame(); + } + break; + case PresentThreadState::error: + break; } + std::this_thread::sleep_for(sleep_duration); } m_activeState = PresentThreadState::stop; } @@ -99,7 +108,19 @@ void KRPresentationThread::renderFrame() KRDevice& device = m_pContext->getDeviceManager()->getDeviceInfo(surface.m_deviceHandle); uint32_t imageIndex = 0; - vkAcquireNextImageKHR(device.m_logicalDevice, surface.m_swapChain, UINT64_MAX, surface.m_imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex); + VkResult result = vkAcquireNextImageKHR(device.m_logicalDevice, surface.m_swapChain, UINT64_MAX, surface.m_imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex); + + if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) { + // TODO - Must explicitly detect resize and trigger swapchain re-creation as well + vkDeviceWaitIdle(device.m_logicalDevice); + if (surface.recreateSwapChain() != VK_SUCCESS) { + m_activeState = PresentThreadState::error; + } + break; + } else if (result != VK_SUCCESS) { + m_activeState = PresentThreadState::error; + break; + } // TODO - this will break with more than one surface... Expect to refactor this out VkCommandBuffer commandBuffer = device.m_graphicsCommandBuffers[imageIndex]; @@ -111,6 +132,7 @@ void KRPresentationThread::renderFrame() beginInfo.pInheritanceInfo = nullptr; if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) { + m_activeState = PresentThreadState::error; // TODO - Add error handling... } @@ -130,6 +152,7 @@ void KRPresentationThread::renderFrame() vkCmdDraw(commandBuffer, 3, 1, 0, 0); vkCmdEndRenderPass(commandBuffer); if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) { + m_activeState = PresentThreadState::error; // TODO - Add error handling... } @@ -149,6 +172,7 @@ void KRPresentationThread::renderFrame() submitInfo.pSignalSemaphores = signalSemaphores; if (vkQueueSubmit(device.m_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE) != VK_SUCCESS) { + m_activeState = PresentThreadState::error; // TODO - Add error handling... } diff --git a/kraken/KRPresentationThread.h b/kraken/KRPresentationThread.h index 4f15a7a..5a29248 100644 --- a/kraken/KRPresentationThread.h +++ b/kraken/KRPresentationThread.h @@ -63,7 +63,7 @@ public: stop = 0, run, pause, - wait_recreate_swapchain + error }; std::atomic m_activeState; diff --git a/kraken/KRSurface.cpp b/kraken/KRSurface.cpp index f09f087..13c1d9c 100644 --- a/kraken/KRSurface.cpp +++ b/kraken/KRSurface.cpp @@ -82,6 +82,36 @@ KrResult KRSurface::initialize() return KR_ERROR_VULKAN; } + return createSwapChain(); +} + +void KRSurface::destroy() +{ + KRDevice& deviceInfo = m_pContext->getDeviceManager()->getDeviceInfo(m_deviceHandle); + + destroySwapChain(); + + if (m_renderFinishedSemaphore != VK_NULL_HANDLE) { + vkDestroySemaphore(deviceInfo.m_logicalDevice, m_renderFinishedSemaphore, nullptr); + m_renderFinishedSemaphore = VK_NULL_HANDLE; + } + + if (m_imageAvailableSemaphore != VK_NULL_HANDLE) { + vkDestroySemaphore(deviceInfo.m_logicalDevice, m_imageAvailableSemaphore, nullptr); + m_imageAvailableSemaphore = VK_NULL_HANDLE; + } + + if (m_surface != VK_NULL_HANDLE) { + vkDestroySurfaceKHR(m_pContext->getDeviceManager()->getVulkanInstance(), m_surface, nullptr); + m_surface = VK_NULL_HANDLE; + } + +} + +KrResult KRSurface::createSwapChain() +{ + KRDevice* deviceInfo = &m_pContext->getDeviceManager()->getDeviceInfo(m_deviceHandle); + VkSurfaceCapabilitiesKHR surfaceCapabilities{}; vkGetPhysicalDeviceSurfaceCapabilitiesKHR(deviceInfo->m_device, m_surface, &surfaceCapabilities); @@ -89,7 +119,6 @@ KrResult KRSurface::initialize() uint32_t formatCount = 0; vkGetPhysicalDeviceSurfaceFormatsKHR(deviceInfo->m_device, m_surface, &formatCount, nullptr); - if (formatCount != 0) { surfaceFormats.resize(formatCount); vkGetPhysicalDeviceSurfaceFormatsKHR(deviceInfo->m_device, m_surface, &formatCount, surfaceFormats.data()); @@ -228,8 +257,11 @@ KrResult KRSurface::initialize() return KR_SUCCESS; } -void KRSurface::destroy() +void KRSurface::destroySwapChain() { + KRPipelineManager* pipelineManager = m_pContext->getPipelineManager(); + // TODO - Destroy the dependent pipeline.. + KRDevice& deviceInfo = m_pContext->getDeviceManager()->getDeviceInfo(m_deviceHandle); for (auto framebuffer : m_swapChainFramebuffers) { @@ -246,20 +278,15 @@ void KRSurface::destroy() vkDestroySwapchainKHR(deviceInfo.m_logicalDevice, m_swapChain, nullptr); m_swapChain = VK_NULL_HANDLE; } - - if (m_renderFinishedSemaphore != VK_NULL_HANDLE) { - vkDestroySemaphore(deviceInfo.m_logicalDevice, m_renderFinishedSemaphore, nullptr); - m_renderFinishedSemaphore = VK_NULL_HANDLE; - } - - if (m_imageAvailableSemaphore != VK_NULL_HANDLE) { - vkDestroySemaphore(deviceInfo.m_logicalDevice, m_imageAvailableSemaphore, nullptr); - m_imageAvailableSemaphore = VK_NULL_HANDLE; - } - - if (m_surface != VK_NULL_HANDLE) { - vkDestroySurfaceKHR(m_pContext->getDeviceManager()->getVulkanInstance(), m_surface, nullptr); - m_surface = VK_NULL_HANDLE; - } - } + +KrResult KRSurface::recreateSwapChain() +{ + destroySwapChain(); + KrResult result = createSwapChain(); + if (result != KR_SUCCESS) { + destroySwapChain(); + } + return result; +} + diff --git a/kraken/KRSurface.h b/kraken/KRSurface.h index a3e2584..06d94be 100644 --- a/kraken/KRSurface.h +++ b/kraken/KRSurface.h @@ -50,6 +50,7 @@ public: KRSurface& operator=(const KRSurface&) = delete; KrResult initialize(); + KrResult recreateSwapChain(); #ifdef WIN32 HWND m_hWnd; @@ -57,7 +58,7 @@ public: KrDeviceHandle m_deviceHandle; VkSurfaceKHR m_surface; VkSwapchainKHR m_swapChain; - std::vector m_swapChainImages; + std::vector m_swapChainImages; VkFormat m_swapChainImageFormat; VkExtent2D m_swapChainExtent; std::vector m_swapChainImageViews; @@ -67,6 +68,8 @@ public: private: + void destroySwapChain(); + KrResult createSwapChain(); }; #endif // KRSURFACE_H