[vulkan] Recreate the surface on surface loss.

According to the Vulkan spec:

> Several WSI functions return `VK_ERROR_SURFACE_LOST_KHR` if the
> surface becomes no longer available. After such an error, the surface
> (and any child swapchain, if one exists) **should** be destroyed, as
> there is no way to restore them to a not-lost state.

So if we get this error, we need to recreate the surface in addition to
the swapchain.
This commit is contained in:
Chip Davis 2019-04-01 12:48:22 -05:00 committed by Philip Rebohle
parent b5f859915a
commit e633dbc06f
2 changed files with 23 additions and 10 deletions

View File

@ -10,8 +10,8 @@ namespace dxvk::vk {
const Rc<DeviceFn>& vkd,
PresenterDevice device,
const PresenterDesc& desc)
: m_vki(vki), m_vkd(vkd), m_device(device) {
if (createSurface(window) != VK_SUCCESS)
: m_vki(vki), m_vkd(vkd), m_device(device), m_window(window) {
if (createSurface() != VK_SUCCESS)
throw DxvkError("Failed to create surface");
if (recreateSwapChain(desc) != VK_SUCCESS)
@ -105,8 +105,20 @@ namespace dxvk::vk {
VkResult status;
if ((status = m_vki->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
m_device.adapter, m_surface, &caps)) != VK_SUCCESS)
return status;
m_device.adapter, m_surface, &caps)) != VK_SUCCESS) {
while (status == VK_ERROR_SURFACE_LOST_KHR) {
// Recreate the surface and try again.
if (m_surface)
destroySurface();
if ((status = createSurface()) != VK_SUCCESS)
continue;
if ((status = m_vki->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
m_device.adapter, m_surface, &caps)) != VK_SUCCESS)
continue;
}
if (status != VK_SUCCESS)
return status;
}
if ((status = getSupportedFormats(formats)) != VK_SUCCESS)
return status;
@ -355,16 +367,16 @@ namespace dxvk::vk {
}
VkResult Presenter::createSurface(HWND window) {
VkResult Presenter::createSurface() {
HINSTANCE instance = reinterpret_cast<HINSTANCE>(
GetWindowLongPtr(window, GWLP_HINSTANCE));
GetWindowLongPtr(m_window, GWLP_HINSTANCE));
VkWin32SurfaceCreateInfoKHR info;
info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
info.pNext = nullptr;
info.flags = 0;
info.hinstance = instance;
info.hwnd = window;
info.hwnd = m_window;
VkResult status = m_vki->vkCreateWin32SurfaceKHR(
m_vki->instance(), &info, nullptr, &m_surface);
@ -412,4 +424,4 @@ namespace dxvk::vk {
m_vki->vkDestroySurfaceKHR(m_vki->instance(), m_surface, nullptr);
}
}
}

View File

@ -174,6 +174,7 @@ namespace dxvk::vk {
PresenterDevice m_device;
PresenterInfo m_info;
HWND m_window = nullptr;
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
@ -213,7 +214,7 @@ namespace dxvk::vk {
VkPresentModeKHR presentMode,
uint32_t desired);
VkResult createSurface(HWND window);
VkResult createSurface();
void destroySwapchain();
@ -221,4 +222,4 @@ namespace dxvk::vk {
};
}
}