Skip to content

Commit 55aae4d

Browse files
committed
vk: Fix NVIDIA crash when resizing the game window quickly
1 parent ad90f8b commit 55aae4d

2 files changed

Lines changed: 28 additions & 5 deletions

File tree

rpcs3/Emu/RSX/VK/VKGSRender.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ class VKGSRender : public GSRender, public ::rsx::reports::ZCULL_control
221221
void frame_context_cleanup(vk::frame_context_t *ctx);
222222
void advance_queued_frames();
223223
void present(vk::frame_context_t *ctx);
224-
void reinitialize_swapchain();
224+
bool reinitialize_swapchain();
225225

226226
vk::viewable_image* get_present_source(vk::present_surface_info* info, const rsx::avconf& avconfig);
227227

rpcs3/Emu/RSX/VK/VKPresent.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ namespace
3333
}
3434
}
3535

36-
void VKGSRender::reinitialize_swapchain()
36+
bool VKGSRender::reinitialize_swapchain()
3737
{
3838
m_swapchain_dims.width = m_frame->client_width();
3939
m_swapchain_dims.height = m_frame->client_height();
@@ -44,7 +44,7 @@ void VKGSRender::reinitialize_swapchain()
4444
if (m_swapchain_dims.width == 0 || m_swapchain_dims.height == 0)
4545
{
4646
swapchain_unavailable = true;
47-
return;
47+
return false;
4848
}
4949

5050
// NOTE: This operation will create a hard sync point
@@ -97,7 +97,7 @@ void VKGSRender::reinitialize_swapchain()
9797
{
9898
rsx_log.warning("Swapchain initialization failed. Request ignored [%dx%d]", m_swapchain_dims.width, m_swapchain_dims.height);
9999
swapchain_unavailable = true;
100-
return;
100+
return false;
101101
}
102102

103103
// Re-initialize CPU frame contexts
@@ -135,6 +135,7 @@ void VKGSRender::reinitialize_swapchain()
135135

136136
swapchain_unavailable = false;
137137
should_reinitialize_swapchain = false;
138+
return true;
138139
}
139140

140141
void VKGSRender::present(vk::frame_context_t *ctx)
@@ -426,11 +427,32 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
426427

427428
if (swapchain_unavailable || should_reinitialize_swapchain)
428429
{
429-
reinitialize_swapchain();
430+
// Reinitializing the swapchain is a failable operation. However, not all failures are fatal (e.g minimized window).
431+
// In the worst case, we can have the driver refuse to create the swapchain while we already deleted the previous one.
432+
// In such scenarios, we have to retry a few times before giving up as we cannot proceed without a swapchain.
433+
for (int i = 0; i < 10; ++i)
434+
{
435+
if (reinitialize_swapchain() || m_current_frame)
436+
{
437+
// If m_current_frame exists, then the initialization failure is non-fatal. Proceed as usual.
438+
break;
439+
}
440+
441+
if (Emu.IsStopped())
442+
{
443+
m_frame->flip(m_context);
444+
rsx::thread::flip(info);
445+
return;
446+
}
447+
448+
std::this_thread::sleep_for(100ms);
449+
}
430450
}
431451

432452
m_profiler.start();
433453

454+
ensure(m_current_frame, "Invalid swapchain setup. Resizing the game window failed.");
455+
434456
if (m_current_frame == &m_aux_frame_context)
435457
{
436458
m_current_frame = &m_frame_context_storage[m_current_queue_index];
@@ -582,6 +604,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
582604
rsx_log.warning("vkAcquireNextImageKHR failed with VK_ERROR_OUT_OF_DATE_KHR. Flip request ignored until surface is recreated.");
583605
swapchain_unavailable = true;
584606
reinitialize_swapchain();
607+
ensure(m_current_frame, "Could not reinitialize swapchain after VK_ERROR_OUT_OF_DATE_KHR signal!");
585608
continue;
586609
default:
587610
vk::die_with_error(status);

0 commit comments

Comments
 (0)