Recreating swap chain when invalidated
This commit is contained in:
@@ -71,15 +71,24 @@ void KRPresentationThread::run()
|
|||||||
m_activeState = PresentThreadState::run;
|
m_activeState = PresentThreadState::run;
|
||||||
while (m_requestedState != PresentThreadRequest::stop)
|
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;
|
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;
|
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;
|
m_activeState = PresentThreadState::stop;
|
||||||
}
|
}
|
||||||
@@ -99,7 +108,19 @@ void KRPresentationThread::renderFrame()
|
|||||||
KRDevice& device = m_pContext->getDeviceManager()->getDeviceInfo(surface.m_deviceHandle);
|
KRDevice& device = m_pContext->getDeviceManager()->getDeviceInfo(surface.m_deviceHandle);
|
||||||
|
|
||||||
uint32_t imageIndex = 0;
|
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
|
// TODO - this will break with more than one surface... Expect to refactor this out
|
||||||
VkCommandBuffer commandBuffer = device.m_graphicsCommandBuffers[imageIndex];
|
VkCommandBuffer commandBuffer = device.m_graphicsCommandBuffers[imageIndex];
|
||||||
@@ -111,6 +132,7 @@ void KRPresentationThread::renderFrame()
|
|||||||
beginInfo.pInheritanceInfo = nullptr;
|
beginInfo.pInheritanceInfo = nullptr;
|
||||||
|
|
||||||
if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) {
|
if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) {
|
||||||
|
m_activeState = PresentThreadState::error;
|
||||||
// TODO - Add error handling...
|
// TODO - Add error handling...
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,6 +152,7 @@ void KRPresentationThread::renderFrame()
|
|||||||
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
|
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
|
||||||
vkCmdEndRenderPass(commandBuffer);
|
vkCmdEndRenderPass(commandBuffer);
|
||||||
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
|
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
|
||||||
|
m_activeState = PresentThreadState::error;
|
||||||
// TODO - Add error handling...
|
// TODO - Add error handling...
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,6 +172,7 @@ void KRPresentationThread::renderFrame()
|
|||||||
submitInfo.pSignalSemaphores = signalSemaphores;
|
submitInfo.pSignalSemaphores = signalSemaphores;
|
||||||
|
|
||||||
if (vkQueueSubmit(device.m_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE) != VK_SUCCESS) {
|
if (vkQueueSubmit(device.m_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE) != VK_SUCCESS) {
|
||||||
|
m_activeState = PresentThreadState::error;
|
||||||
// TODO - Add error handling...
|
// TODO - Add error handling...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public:
|
|||||||
stop = 0,
|
stop = 0,
|
||||||
run,
|
run,
|
||||||
pause,
|
pause,
|
||||||
wait_recreate_swapchain
|
error
|
||||||
};
|
};
|
||||||
std::atomic<PresentThreadState> m_activeState;
|
std::atomic<PresentThreadState> m_activeState;
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,36 @@ KrResult KRSurface::initialize()
|
|||||||
return KR_ERROR_VULKAN;
|
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{};
|
VkSurfaceCapabilitiesKHR surfaceCapabilities{};
|
||||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(deviceInfo->m_device, m_surface, &surfaceCapabilities);
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(deviceInfo->m_device, m_surface, &surfaceCapabilities);
|
||||||
|
|
||||||
@@ -89,7 +119,6 @@ KrResult KRSurface::initialize()
|
|||||||
uint32_t formatCount = 0;
|
uint32_t formatCount = 0;
|
||||||
vkGetPhysicalDeviceSurfaceFormatsKHR(deviceInfo->m_device, m_surface, &formatCount, nullptr);
|
vkGetPhysicalDeviceSurfaceFormatsKHR(deviceInfo->m_device, m_surface, &formatCount, nullptr);
|
||||||
|
|
||||||
|
|
||||||
if (formatCount != 0) {
|
if (formatCount != 0) {
|
||||||
surfaceFormats.resize(formatCount);
|
surfaceFormats.resize(formatCount);
|
||||||
vkGetPhysicalDeviceSurfaceFormatsKHR(deviceInfo->m_device, m_surface, &formatCount, surfaceFormats.data());
|
vkGetPhysicalDeviceSurfaceFormatsKHR(deviceInfo->m_device, m_surface, &formatCount, surfaceFormats.data());
|
||||||
@@ -228,8 +257,11 @@ KrResult KRSurface::initialize()
|
|||||||
return KR_SUCCESS;
|
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);
|
KRDevice& deviceInfo = m_pContext->getDeviceManager()->getDeviceInfo(m_deviceHandle);
|
||||||
|
|
||||||
for (auto framebuffer : m_swapChainFramebuffers) {
|
for (auto framebuffer : m_swapChainFramebuffers) {
|
||||||
@@ -246,20 +278,15 @@ void KRSurface::destroy()
|
|||||||
vkDestroySwapchainKHR(deviceInfo.m_logicalDevice, m_swapChain, nullptr);
|
vkDestroySwapchainKHR(deviceInfo.m_logicalDevice, m_swapChain, nullptr);
|
||||||
m_swapChain = VK_NULL_HANDLE;
|
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;
|
KRSurface& operator=(const KRSurface&) = delete;
|
||||||
|
|
||||||
KrResult initialize();
|
KrResult initialize();
|
||||||
|
KrResult recreateSwapChain();
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
HWND m_hWnd;
|
HWND m_hWnd;
|
||||||
@@ -67,6 +68,8 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void destroySwapChain();
|
||||||
|
KrResult createSwapChain();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KRSURFACE_H
|
#endif // KRSURFACE_H
|
||||||
|
|||||||
Reference in New Issue
Block a user