Fix: disable hardware acceleration when GPU driver crashed the game last attempt (#10928)

This commit is contained in:
Patric Stout 2023-06-04 16:40:17 +02:00 committed by GitHub
parent 556b44713e
commit 0e56a73fb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 1 deletions

View File

@ -16,8 +16,15 @@
#include "video/video_driver.hpp"
#include "string_func.h"
#include "table/strings.h"
#include "fileio_func.h"
#include <sstream>
#ifdef _WIN32
# include <windows.h>
#else
# include <unistd.h>
#endif /* _WIN32 */
#include "safeguards.h"
std::string _ini_videodriver; ///< The video driver a stored in the configuration file.
@ -32,6 +39,8 @@ std::string _ini_musicdriver; ///< The music driver a stored in the confi
std::string _ini_blitter; ///< The blitter as stored in the configuration file.
bool _blitter_autodetected; ///< Was the blitter autodetected or specified by the user?
static const std::string HWACCELERATION_TEST_FILE = "hwaccel.dat"; ///< Filename to test if we crashed last time we tried to use hardware acceleration.
/**
* Get a string parameter the list of parameters.
* @param parm The parameters.
@ -114,6 +123,27 @@ bool DriverFactoryBase::SelectDriverImpl(const std::string &name, Driver::Type t
if (type == Driver::DT_VIDEO && !_video_hw_accel && d->UsesHardwareAcceleration()) continue;
if (type == Driver::DT_VIDEO && _video_hw_accel && d->UsesHardwareAcceleration()) {
/* Check if we have already tried this driver in last run.
* If it is here, it most likely means we crashed. So skip
* hardware acceleration. */
auto filename = FioFindFullPath(BASE_DIR, HWACCELERATION_TEST_FILE);
if (!filename.empty()) {
unlink(filename.c_str());
Debug(driver, 1, "Probing {} driver '{}' skipped due to earlier crash", GetDriverTypeName(type), d->name);
_video_hw_accel = false;
ErrorMessageData msg(STR_VIDEO_DRIVER_ERROR, STR_VIDEO_DRIVER_ERROR_HARDWARE_ACCELERATION_CRASH, true);
ScheduleErrorMessage(msg);
continue;
}
/* Write empty file to note we are attempting hardware acceleration. */
auto f = FioFOpenFile(HWACCELERATION_TEST_FILE, "w", BASE_DIR);
FioFCloseFile(f);
}
Driver *oldd = *GetActiveDriver(type);
Driver *newd = d->CreateInstance();
*GetActiveDriver(type) = newd;
@ -131,7 +161,7 @@ bool DriverFactoryBase::SelectDriverImpl(const std::string &name, Driver::Type t
if (type == Driver::DT_VIDEO && _video_hw_accel && d->UsesHardwareAcceleration()) {
_video_hw_accel = false;
ErrorMessageData msg(STR_VIDEO_DRIVER_ERROR, STR_VIDEO_DRIVER_ERROR_NO_HARDWARE_ACCELERATION);
ErrorMessageData msg(STR_VIDEO_DRIVER_ERROR, STR_VIDEO_DRIVER_ERROR_NO_HARDWARE_ACCELERATION, true);
ScheduleErrorMessage(msg);
}
}
@ -177,6 +207,18 @@ bool DriverFactoryBase::SelectDriverImpl(const std::string &name, Driver::Type t
}
}
/**
* Mark the current video driver as operational.
*/
void DriverFactoryBase::MarkVideoDriverOperational()
{
/* As part of the detection whether the GPU driver crashes the game,
* and as we are operational now, remove the hardware acceleration
* test-file. */
auto filename = FioFindFullPath(BASE_DIR, HWACCELERATION_TEST_FILE);
if (!filename.empty()) unlink(filename.c_str());
}
/**
* Build a human readable list of available drivers, grouped by type.
* @param output_iterator The iterator to write the string to.

View File

@ -100,6 +100,8 @@ private:
static bool SelectDriverImpl(const std::string &name, Driver::Type type);
static void MarkVideoDriverOperational();
protected:
DriverFactoryBase(Driver::Type type, int priority, const char *name, const char *description);

View File

@ -2080,6 +2080,7 @@ STR_CONFIG_ERROR_SPRITECACHE_TOO_BIG :{WHITE}Allocati
# Video initalization errors
STR_VIDEO_DRIVER_ERROR :{WHITE}Error with video settings...
STR_VIDEO_DRIVER_ERROR_NO_HARDWARE_ACCELERATION :{WHITE}... no compatible GPU found. Hardware acceleration disabled
STR_VIDEO_DRIVER_ERROR_HARDWARE_ACCELERATION_CRASH :{WHITE}... GPU driver crashed the game. Hardware acceleration disabled
# Intro window
STR_INTRO_CAPTION :{WHITE}OpenTTD {REV}

View File

@ -12,6 +12,7 @@
#include "../network/network.h"
#include "../blitter/factory.hpp"
#include "../debug.h"
#include "../driver.h"
#include "../fontcache.h"
#include "../gfx_func.h"
#include "../gfxinit.h"
@ -156,6 +157,13 @@ void VideoDriver::Tick()
this->Paint();
this->UnlockVideoBuffer();
/* Wait till the first successful drawing tick before marking the driver as operational. */
static bool first_draw_tick = true;
if (first_draw_tick) {
first_draw_tick = false;
DriverFactoryBase::MarkVideoDriverOperational();
}
}
}