mirror of
				https://github.com/hedge-dev/UnleashedRecomp.git
				synced 2025-10-30 07:11:05 +00:00 
			
		
		
		
	Implement a mechanism to survive from GPU driver crashes on Windows. (#1480)
	
		
			
	
		
	
	
		
	
		
			Some checks are pending
		
		
	
	
		
			
				
	
				validate-internal / build (push) Waiting to run
				
			
		
		
	
	
				
					
				
			
		
			Some checks are pending
		
		
	
	validate-internal / build (push) Waiting to run
				
			This commit is contained in:
		
							parent
							
								
									b282cbc4a2
								
							
						
					
					
						commit
						49d3b675ed
					
				
					 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> | ||||
|  | @ -1652,7 +1653,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; | ||||
|  | @ -1672,6 +1673,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 | ||||
|  | @ -1680,9 +1687,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) | ||||
|             { | ||||
|  | @ -1719,6 +1734,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) | ||||
|  | @ -1726,6 +1757,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(); | ||||
|  |  | |||
|  | @ -208,6 +208,7 @@ int main(int argc, char *argv[]) | |||
|     bool forceDLCInstaller = false; | ||||
|     bool useDefaultWorkingDirectory = false; | ||||
|     bool forceInstallationCheck = false; | ||||
|     bool graphicsApiRetry = false; | ||||
|     const char *sdlVideoDriver = nullptr; | ||||
| 
 | ||||
|     for (uint32_t i = 1; i < argc; i++) | ||||
|  | @ -216,6 +217,7 @@ int main(int argc, char *argv[]) | |||
|         forceDLCInstaller = forceDLCInstaller || (strcmp(argv[i], "--install-dlc") == 0); | ||||
|         useDefaultWorkingDirectory = useDefaultWorkingDirectory || (strcmp(argv[i], "--use-cwd") == 0); | ||||
|         forceInstallationCheck = forceInstallationCheck || (strcmp(argv[i], "--install-check") == 0); | ||||
|         graphicsApiRetry = graphicsApiRetry || (strcmp(argv[i], "--graphics-api-retry") == 0); | ||||
| 
 | ||||
|         if (strcmp(argv[i], "--sdl-video-driver") == 0) | ||||
|         { | ||||
|  | @ -326,7 +328,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); | ||||
|  | @ -346,7 +348,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
		
		Reference in a new issue
	
	 Skyth (Asilkan)
						Skyth (Asilkan)