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 <user/config.h>
|
||||||
#include <sdl_listener.h>
|
#include <sdl_listener.h>
|
||||||
#include <xxHashMap.h>
|
#include <xxHashMap.h>
|
||||||
|
#include <os/process.h>
|
||||||
|
|
||||||
#if defined(ASYNC_PSO_DEBUG) || defined(PSO_CACHING)
|
#if defined(ASYNC_PSO_DEBUG) || defined(PSO_CACHING)
|
||||||
#include <magic_enum/magic_enum.hpp>
|
#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++)
|
for (uint32_t i = 0; i < 16; i++)
|
||||||
g_inputSlots[i].index = i;
|
g_inputSlots[i].index = i;
|
||||||
|
@ -1671,6 +1672,12 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver)
|
||||||
std::vector<RenderInterfaceFunction *> interfaceFunctions;
|
std::vector<RenderInterfaceFunction *> interfaceFunctions;
|
||||||
|
|
||||||
#ifdef UNLEASHED_RECOMP_D3D12
|
#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 ? CreateVulkanInterfaceWrapper : CreateD3D12Interface);
|
||||||
interfaceFunctions.push_back(g_vulkan ? CreateD3D12Interface : CreateVulkanInterfaceWrapper);
|
interfaceFunctions.push_back(g_vulkan ? CreateD3D12Interface : CreateVulkanInterfaceWrapper);
|
||||||
#else
|
#else
|
||||||
|
@ -1679,9 +1686,17 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver)
|
||||||
|
|
||||||
for (RenderInterfaceFunction *interfaceFunction : interfaceFunctions)
|
for (RenderInterfaceFunction *interfaceFunction : interfaceFunctions)
|
||||||
{
|
{
|
||||||
g_interface = interfaceFunction();
|
#ifdef UNLEASHED_RECOMP_D3D12
|
||||||
if (g_interface != nullptr)
|
// 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);
|
g_device = g_interface->createDevice(Config::GraphicsDevice);
|
||||||
if (g_device != nullptr)
|
if (g_device != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -1718,6 +1733,22 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver)
|
||||||
break;
|
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)
|
if (g_device == nullptr)
|
||||||
|
@ -1725,6 +1756,14 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver)
|
||||||
return false;
|
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();
|
g_capabilities = g_device->getCapabilities();
|
||||||
|
|
||||||
LoadEmbeddedResources();
|
LoadEmbeddedResources();
|
||||||
|
|
|
@ -18,7 +18,7 @@ struct Video
|
||||||
static inline uint32_t s_viewportWidth;
|
static inline uint32_t s_viewportWidth;
|
||||||
static inline uint32_t s_viewportHeight;
|
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 WaitOnSwapChain();
|
||||||
static void Present();
|
static void Present();
|
||||||
static void StartPipelinePrecompilation();
|
static void StartPipelinePrecompilation();
|
||||||
|
|
|
@ -200,6 +200,7 @@ int main(int argc, char *argv[])
|
||||||
bool forceInstaller = false;
|
bool forceInstaller = false;
|
||||||
bool forceDLCInstaller = false;
|
bool forceDLCInstaller = false;
|
||||||
bool useDefaultWorkingDirectory = false;
|
bool useDefaultWorkingDirectory = false;
|
||||||
|
bool graphicsApiRetry = false;
|
||||||
const char *sdlVideoDriver = nullptr;
|
const char *sdlVideoDriver = nullptr;
|
||||||
|
|
||||||
for (uint32_t i = 1; i < argc; i++)
|
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);
|
forceInstaller = forceInstaller || (strcmp(argv[i], "--install") == 0);
|
||||||
forceDLCInstaller = forceDLCInstaller || (strcmp(argv[i], "--install-dlc") == 0);
|
forceDLCInstaller = forceDLCInstaller || (strcmp(argv[i], "--install-dlc") == 0);
|
||||||
useDefaultWorkingDirectory = useDefaultWorkingDirectory || (strcmp(argv[i], "--use-cwd") == 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)
|
if (strcmp(argv[i], "--sdl-video-driver") == 0)
|
||||||
{
|
{
|
||||||
|
@ -261,7 +263,7 @@ int main(int argc, char *argv[])
|
||||||
bool runInstallerWizard = forceInstaller || forceDLCInstaller || !isGameInstalled;
|
bool runInstallerWizard = forceInstaller || forceDLCInstaller || !isGameInstalled;
|
||||||
if (runInstallerWizard)
|
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);
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, GameWindow::GetTitle(), Localise("Video_BackendError").c_str(), GameWindow::s_pWindow);
|
||||||
std::_Exit(1);
|
std::_Exit(1);
|
||||||
|
@ -281,7 +283,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
if (!runInstallerWizard)
|
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);
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, GameWindow::GetTitle(), Localise("Video_BackendError").c_str(), GameWindow::s_pWindow);
|
||||||
std::_Exit(1);
|
std::_Exit(1);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue