Work around maximal extent size of 0x0 when the game is minimized.

Some GPU drivers set a maximal extent size of 0x0 when the window gets
minimized. One example is Intel on Windows. A swapchain with extent
size of 0x0 is invalid, so we cannot reinitialize the renderer... Work
around that by postponing the restart as long as the maxmimal extent
size stays 0x0.

This could should be done in the client (don't call into th renderer
when the window is minimized), but it would need a lot of changes
to the client <-> renderer interactions. So take the easy route.
This commit is contained in:
Yamagi 2021-04-23 15:00:20 +02:00
parent dd80702913
commit c543d3cc05

View file

@ -1383,6 +1383,42 @@ RE_BeginFrame( float camera_separation )
return; return;
} }
/* Some GPU drivers set a maximum extent size of 0x0 when
the window is minimized. But a swapchain with an extent
size of 0x0 is invalid. This leads to the following
problem:
1. The window is minimized, the extent size changes and
the Vulkan state get's corrupted. QVk_EndFrame()
above or QVk_BeginFrame() below detect the Vulkan
state as corrupted, set vk_frameStated to false and
request a restart by setting vk_restartNeeded to
true.
2. RE_EndFrame() triggers the restart. QVk_Shutdown()
is successfull, but QVk_Init() can't create a valid
swapchains and errors out. An incomplete internal
renderer state is left behind. The only way out is
to trigger a full render restart.
3. The full renderer restart would lead to a restart
loop: Restart -> QVk_Init() fails -> restart -> ...
The only alternative is not to restart. Instead the
renderer could error out, that would print an error
message and quit the client.
Work around this by not starting the frame or restarting
the renderer, as long as the maximum extent size is 0x0.
This is part 1 (the state corruption war detect in the
last frame), part 2 (the state corruption was detected in
the current frame) is in RE_EndFrame(). */
if (vk_restartNeeded)
{
if (!QVk_CheckExtent())
{
vk_frameStarted = false;
return;
}
}
// if ri.Sys_Error() had been issued mid-frame, we might end up here without properly submitting the image, so call QVk_EndFrame to be safe // if ri.Sys_Error() had been issued mid-frame, we might end up here without properly submitting the image, so call QVk_EndFrame to be safe
if (QVk_EndFrame(true) != VK_SUCCESS) if (QVk_EndFrame(true) != VK_SUCCESS)
vk_restartNeeded = true; vk_restartNeeded = true;
@ -1432,10 +1468,16 @@ RE_EndFrame( void )
// world has not rendered yet // world has not rendered yet
world_rendered = false; world_rendered = false;
/* Part two of the 'maximum extent size may be 0x0'
* work around. See the explanation in RE_BeginFrame()
* for details. */
if (vk_restartNeeded) if (vk_restartNeeded)
{ {
QVk_Restart(); if (QVk_CheckExtent())
vk_restartNeeded = false; {
QVk_Restart();
vk_restartNeeded = false;
}
} }
} }