mirror of
https://github.com/love2d/love.git
synced 2026-08-12 08:30:56 +02:00
vulkan: handle swap chain surface loss errors.
This commit is contained in:
@@ -606,7 +606,7 @@ void Graphics::present(void *screenshotCallbackdata)
|
|||||||
{
|
{
|
||||||
VkExtent2D extent = chooseSwapExtent(capabilities);
|
VkExtent2D extent = chooseSwapExtent(capabilities);
|
||||||
if (extent.width > 0 && extent.height > 0)
|
if (extent.width > 0 && extent.height > 0)
|
||||||
swapChainRecreationRequested = true;
|
swapChainRequestFlags |= SWAP_CHAIN_REQUEST_RECREATE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -625,9 +625,12 @@ void Graphics::present(void *screenshotCallbackdata)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || swapChainRecreationRequested)
|
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || result == VK_ERROR_SURFACE_LOST_KHR
|
||||||
|
|| swapChainRequestFlags != SWAP_CHAIN_REQUEST_KEEP)
|
||||||
{
|
{
|
||||||
swapChainRecreationRequested = false;
|
swapChainRequestFlags |= SWAP_CHAIN_REQUEST_RECREATE;
|
||||||
|
if (result == VK_ERROR_SURFACE_LOST_KHR)
|
||||||
|
swapChainRequestFlags |= SWAP_CHAIN_REQUEST_RECREATE_SURFACE;
|
||||||
recreateSwapChain();
|
recreateSwapChain();
|
||||||
}
|
}
|
||||||
else if (result != VK_SUCCESS)
|
else if (result != VK_SUCCESS)
|
||||||
@@ -666,9 +669,8 @@ void Graphics::backbufferChanged(const BackbufferSettings &settings)
|
|||||||
// Don't wait until the next frame starts to recreate the swapchain - doing so
|
// Don't wait until the next frame starts to recreate the swapchain - doing so
|
||||||
// will cause a 1 frame delay in the backbuffer size on resize, and it can cause
|
// will cause a 1 frame delay in the backbuffer size on resize, and it can cause
|
||||||
// MSAA state to get out of sync for a frame.
|
// MSAA state to get out of sync for a frame.
|
||||||
if (swapChainRecreationRequested)
|
if (swapChainRequestFlags != SWAP_CHAIN_REQUEST_KEEP)
|
||||||
{
|
{
|
||||||
swapChainRecreationRequested = false;
|
|
||||||
submitGpuCommands(SUBMIT_NOPRESENT);
|
submitGpuCommands(SUBMIT_NOPRESENT);
|
||||||
recreateSwapChain();
|
recreateSwapChain();
|
||||||
beginSwapChainFrame();
|
beginSwapChainFrame();
|
||||||
@@ -841,12 +843,7 @@ void Graphics::unSetMode()
|
|||||||
created = false;
|
created = false;
|
||||||
|
|
||||||
cleanupSwapChain(true);
|
cleanupSwapChain(true);
|
||||||
|
cleanupSurface();
|
||||||
if (surface != VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
vkDestroySurfaceKHR(instance, surface, nullptr);
|
|
||||||
surface = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::setActive(bool enable)
|
void Graphics::setActive(bool enable)
|
||||||
@@ -1386,8 +1383,15 @@ void Graphics::beginSwapChainFrame()
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
|
VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
|
||||||
if (result == VK_ERROR_OUT_OF_DATE_KHR)
|
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_ERROR_SURFACE_LOST_KHR)
|
||||||
{
|
{
|
||||||
|
swapChainRequestFlags |= SWAP_CHAIN_REQUEST_RECREATE;
|
||||||
|
if (result == VK_ERROR_SURFACE_LOST_KHR)
|
||||||
|
{
|
||||||
|
// TODO: do we need to worry about an infinite loop here if the surface keeps getting lost?
|
||||||
|
// What should happen if creation fails?
|
||||||
|
swapChainRequestFlags |= SWAP_CHAIN_REQUEST_RECREATE_SURFACE;
|
||||||
|
}
|
||||||
recreateSwapChain();
|
recreateSwapChain();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1996,6 +2000,15 @@ void Graphics::createSurface()
|
|||||||
throw love::Exception("Failed to create Vulkan window surface: %s", SDL_GetError());
|
throw love::Exception("Failed to create Vulkan window surface: %s", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Graphics::cleanupSurface()
|
||||||
|
{
|
||||||
|
if (surface != VK_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
vkDestroySurfaceKHR(instance, surface, nullptr);
|
||||||
|
surface = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SwapChainSupportDetails Graphics::querySwapChainSupport(VkPhysicalDevice device)
|
SwapChainSupportDetails Graphics::querySwapChainSupport(VkPhysicalDevice device)
|
||||||
{
|
{
|
||||||
SwapChainSupportDetails details;
|
SwapChainSupportDetails details;
|
||||||
@@ -2984,7 +2997,7 @@ void Graphics::requestSwapchainRecreation()
|
|||||||
{
|
{
|
||||||
if (swapChain != VK_NULL_HANDLE)
|
if (swapChain != VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
swapChainRecreationRequested = true;
|
swapChainRequestFlags |= SWAP_CHAIN_REQUEST_RECREATE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3566,13 +3579,21 @@ void Graphics::recreateSwapChain()
|
|||||||
{
|
{
|
||||||
vkDeviceWaitIdle(device);
|
vkDeviceWaitIdle(device);
|
||||||
|
|
||||||
cleanupSwapChain(false);
|
bool destroySwapChainObject = (swapChainRequestFlags & SWAP_CHAIN_REQUEST_RECREATE_SURFACE) != 0;
|
||||||
|
cleanupSwapChain(destroySwapChainObject);
|
||||||
|
|
||||||
|
if ((swapChainRequestFlags & SWAP_CHAIN_REQUEST_RECREATE_SURFACE) != 0)
|
||||||
|
{
|
||||||
|
cleanupSurface();
|
||||||
|
createSurface();
|
||||||
|
}
|
||||||
|
|
||||||
createSwapChain();
|
createSwapChain();
|
||||||
createImageViews();
|
createImageViews();
|
||||||
createColorResources();
|
createColorResources();
|
||||||
createDepthResources();
|
createDepthResources();
|
||||||
|
|
||||||
|
swapChainRequestFlags = SWAP_CHAIN_REQUEST_KEEP;
|
||||||
transitionColorDepthLayouts = true;
|
transitionColorDepthLayouts = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -305,6 +305,13 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
enum SwapChainRequestFlags
|
||||||
|
{
|
||||||
|
SWAP_CHAIN_REQUEST_KEEP = 0,
|
||||||
|
SWAP_CHAIN_REQUEST_RECREATE = (1 << 0),
|
||||||
|
SWAP_CHAIN_REQUEST_RECREATE_SURFACE = (1 << 1),
|
||||||
|
};
|
||||||
|
|
||||||
struct SharedDescriptorPoolsRef
|
struct SharedDescriptorPoolsRef
|
||||||
{
|
{
|
||||||
SharedDescriptorPools *pools = nullptr;
|
SharedDescriptorPools *pools = nullptr;
|
||||||
@@ -319,6 +326,7 @@ private:
|
|||||||
void createPipelineCache();
|
void createPipelineCache();
|
||||||
void initVMA();
|
void initVMA();
|
||||||
void createSurface();
|
void createSurface();
|
||||||
|
void cleanupSurface();
|
||||||
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device);
|
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device);
|
||||||
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR> &availableFormats);
|
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR> &availableFormats);
|
||||||
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes);
|
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes);
|
||||||
@@ -405,7 +413,7 @@ private:
|
|||||||
size_t currentFrame = 0;
|
size_t currentFrame = 0;
|
||||||
uint32_t imageIndex = 0;
|
uint32_t imageIndex = 0;
|
||||||
uint64 realFrameIndex = 0;
|
uint64 realFrameIndex = 0;
|
||||||
bool swapChainRecreationRequested = false;
|
uint32 swapChainRequestFlags = 0;
|
||||||
bool windowIsFullscreenExclusive = false;
|
bool windowIsFullscreenExclusive = false;
|
||||||
bool transitionColorDepthLayouts = false;
|
bool transitionColorDepthLayouts = false;
|
||||||
VmaAllocator vmaAllocator = VK_NULL_HANDLE;
|
VmaAllocator vmaAllocator = VK_NULL_HANDLE;
|
||||||
|
|||||||
Reference in New Issue
Block a user