Recreating swap chain when invalidated
This commit is contained in:
@@ -71,15 +71,24 @@ void KRPresentationThread::run()
|
||||
m_activeState = PresentThreadState::run;
|
||||
while (m_requestedState != PresentThreadRequest::stop)
|
||||
{
|
||||
while (m_requestedState == PresentThreadRequest::run) {
|
||||
switch (m_activeState) {
|
||||
case PresentThreadState::pause:
|
||||
case PresentThreadState::stop:
|
||||
if (m_requestedState == PresentThreadRequest::run) {
|
||||
m_activeState = PresentThreadState::run;
|
||||
renderFrame();
|
||||
std::this_thread::sleep_for(sleep_duration);
|
||||
}
|
||||
while (m_requestedState == PresentThreadRequest::pause) {
|
||||
break;
|
||||
case PresentThreadState::run:
|
||||
if (m_requestedState == PresentThreadRequest::pause) {
|
||||
m_activeState = PresentThreadState::pause;
|
||||
std::this_thread::sleep_for(sleep_duration);
|
||||
} 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...
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
stop = 0,
|
||||
run,
|
||||
pause,
|
||||
wait_recreate_swapchain
|
||||
error
|
||||
};
|
||||
std::atomic<PresentThreadState> m_activeState;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
KRSurface& operator=(const KRSurface&) = delete;
|
||||
|
||||
KrResult initialize();
|
||||
KrResult recreateSwapChain();
|
||||
|
||||
#ifdef WIN32
|
||||
HWND m_hWnd;
|
||||
@@ -67,6 +68,8 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
void destroySwapChain();
|
||||
KrResult createSwapChain();
|
||||
};
|
||||
|
||||
#endif // KRSURFACE_H
|
||||
|
||||
Reference in New Issue
Block a user