mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-04-28 21:37:58 +03:00
Implement a mechanism to survive from GPU driver crashes on Windows.
This commit is contained in:
parent
4b4c439709
commit
7726afeb29
3 changed files with 47 additions and 6 deletions
|
@ -31,6 +31,7 @@
|
|||
#include <user/config.h>
|
||||
#include <sdl_listener.h>
|
||||
#include <xxHashMap.h>
|
||||
#include <os/process.h>
|
||||
|
||||
#if defined(ASYNC_PSO_DEBUG) || defined(PSO_CACHING)
|
||||
#include <magic_enum/magic_enum.hpp>
|
||||
|
@ -1651,7 +1652,7 @@ static void ApplyLowEndDefaults()
|
|||
}
|
||||
}
|
||||
|
||||
bool Video::CreateHostDevice(const char *sdlVideoDriver)
|
||||
bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
g_inputSlots[i].index = i;
|
||||
|
@ -1671,6 +1672,12 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver)
|
|||
std::vector<RenderInterfaceFunction *> interfaceFunctions;
|
||||
|
||||
#ifdef UNLEASHED_RECOMP_D3D12
|
||||
if (graphicsApiRetry)
|
||||
{
|
||||
// If we are attempting to create again after a reboot due to a crash, swap the order.
|
||||
g_vulkan = !g_vulkan;
|
||||
}
|
||||
|
||||
interfaceFunctions.push_back(g_vulkan ? CreateVulkanInterfaceWrapper : CreateD3D12Interface);
|
||||
interfaceFunctions.push_back(g_vulkan ? CreateD3D12Interface : CreateVulkanInterfaceWrapper);
|
||||
#else
|
||||
|
@ -1679,9 +1686,17 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver)
|
|||
|
||||
for (RenderInterfaceFunction *interfaceFunction : interfaceFunctions)
|
||||
{
|
||||
g_interface = interfaceFunction();
|
||||
if (g_interface != nullptr)
|
||||
#ifdef UNLEASHED_RECOMP_D3D12
|
||||
// Wrap the device creation in __try/__except to survive from driver crashes.
|
||||
__try
|
||||
#endif
|
||||
{
|
||||
g_interface = interfaceFunction();
|
||||
if (g_interface == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
g_device = g_interface->createDevice(Config::GraphicsDevice);
|
||||
if (g_device != nullptr)
|
||||
{
|
||||
|
@ -1718,6 +1733,22 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver)
|
|||
break;
|
||||
}
|
||||
}
|
||||
#ifdef UNLEASHED_RECOMP_D3D12
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
if (graphicsApiRetry)
|
||||
{
|
||||
// If we were retrying, and this also failed, then we'll show the user neither of the graphics APIs succeeded.
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this is the first crash we ran into, reboot and try the other graphics API.
|
||||
os::process::StartProcess(os::process::GetExecutablePath(), { "--graphics-api-retry" });
|
||||
std::_Exit(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (g_device == nullptr)
|
||||
|
@ -1725,6 +1756,14 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver)
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef UNLEASHED_RECOMP_D3D12
|
||||
if (graphicsApiRetry)
|
||||
{
|
||||
// If we managed to create a device after retrying it in a reboot, remember the one we picked.
|
||||
Config::GraphicsAPI = g_vulkan ? EGraphicsAPI::Vulkan : EGraphicsAPI::D3D12;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_capabilities = g_device->getCapabilities();
|
||||
|
||||
LoadEmbeddedResources();
|
||||
|
|
|
@ -18,7 +18,7 @@ struct Video
|
|||
static inline uint32_t s_viewportWidth;
|
||||
static inline uint32_t s_viewportHeight;
|
||||
|
||||
static bool CreateHostDevice(const char *sdlVideoDriver);
|
||||
static bool CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry);
|
||||
static void WaitOnSwapChain();
|
||||
static void Present();
|
||||
static void StartPipelinePrecompilation();
|
||||
|
|
|
@ -200,6 +200,7 @@ int main(int argc, char *argv[])
|
|||
bool forceInstaller = false;
|
||||
bool forceDLCInstaller = false;
|
||||
bool useDefaultWorkingDirectory = false;
|
||||
bool graphicsApiRetry = false;
|
||||
const char *sdlVideoDriver = nullptr;
|
||||
|
||||
for (uint32_t i = 1; i < argc; i++)
|
||||
|
@ -207,6 +208,7 @@ int main(int argc, char *argv[])
|
|||
forceInstaller = forceInstaller || (strcmp(argv[i], "--install") == 0);
|
||||
forceDLCInstaller = forceDLCInstaller || (strcmp(argv[i], "--install-dlc") == 0);
|
||||
useDefaultWorkingDirectory = useDefaultWorkingDirectory || (strcmp(argv[i], "--use-cwd") == 0);
|
||||
graphicsApiRetry = graphicsApiRetry || (strcmp(argv[i], "--graphics-api-retry") == 0);
|
||||
|
||||
if (strcmp(argv[i], "--sdl-video-driver") == 0)
|
||||
{
|
||||
|
@ -261,7 +263,7 @@ int main(int argc, char *argv[])
|
|||
bool runInstallerWizard = forceInstaller || forceDLCInstaller || !isGameInstalled;
|
||||
if (runInstallerWizard)
|
||||
{
|
||||
if (!Video::CreateHostDevice(sdlVideoDriver))
|
||||
if (!Video::CreateHostDevice(sdlVideoDriver, graphicsApiRetry))
|
||||
{
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, GameWindow::GetTitle(), Localise("Video_BackendError").c_str(), GameWindow::s_pWindow);
|
||||
std::_Exit(1);
|
||||
|
@ -281,7 +283,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
if (!runInstallerWizard)
|
||||
{
|
||||
if (!Video::CreateHostDevice(sdlVideoDriver))
|
||||
if (!Video::CreateHostDevice(sdlVideoDriver, graphicsApiRetry))
|
||||
{
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, GameWindow::GetTitle(), Localise("Video_BackendError").c_str(), GameWindow::s_pWindow);
|
||||
std::_Exit(1);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue