Don't fill backend info when core is running

The current approach results in the UI thread creating a graphics device
whilst the core is running, leading to races on function pointers, and
potentially crashing.
This commit is contained in:
Stenzek 2018-09-28 14:22:18 +10:00
parent a877d5f6dc
commit 93923e2b29
3 changed files with 21 additions and 15 deletions

View File

@ -38,9 +38,6 @@ void GraphicsWindow::Initialize()
m_lazy_initialized = true; m_lazy_initialized = true;
g_Config.Refresh();
g_video_backend->InitBackendInfo();
CreateMainLayout(); CreateMainLayout();
setWindowTitle(tr("Graphics")); setWindowTitle(tr("Graphics"));
@ -109,18 +106,7 @@ void GraphicsWindow::CreateMainLayout()
void GraphicsWindow::OnBackendChanged(const QString& backend_name) void GraphicsWindow::OnBackendChanged(const QString& backend_name)
{ {
SConfig::GetInstance().m_strVideoBackend = backend_name.toStdString(); SConfig::GetInstance().m_strVideoBackend = backend_name.toStdString();
VideoBackendBase::PopulateBackendInfo();
for (const auto& backend : g_available_video_backends)
{
if (backend->GetName() == backend_name.toStdString())
{
g_Config.Refresh();
g_video_backend = backend.get();
g_video_backend->InitBackendInfo();
break;
}
}
setWindowTitle( setWindowTitle(
tr("%1 Graphics Configuration").arg(tr(g_video_backend->GetDisplayName().c_str()))); tr("%1 Graphics Configuration").arg(tr(g_video_backend->GetDisplayName().c_str())));

View File

@ -14,6 +14,8 @@
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Event.h" #include "Common/Event.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/Host.h" #include "Core/Host.h"
// TODO: ugly // TODO: ugly
@ -223,6 +225,20 @@ void VideoBackendBase::ActivateBackend(const std::string& name)
g_video_backend = iter->get(); g_video_backend = iter->get();
} }
void VideoBackendBase::PopulateBackendInfo()
{
// If the core is running, the backend info will have been populated already.
// If we did it here, the UI thread can race with the with the GPU thread.
if (Core::IsRunning())
return;
// We refresh the config after initializing the backend info, as system-specific settings
// such as anti-aliasing, or the selected adapter may be invalid, and should be checked.
ActivateBackend(SConfig::GetInstance().m_strVideoBackend);
g_video_backend->InitBackendInfo();
g_Config.Refresh();
}
// Run from the CPU thread // Run from the CPU thread
void VideoBackendBase::DoState(PointerWrap& p) void VideoBackendBase::DoState(PointerWrap& p)
{ {

View File

@ -54,6 +54,10 @@ public:
static void ClearList(); static void ClearList();
static void ActivateBackend(const std::string& name); static void ActivateBackend(const std::string& name);
// Fills the backend_info fields with the capabilities of the selected backend/device.
// Called by the UI thread when the graphics config is opened.
static void PopulateBackendInfo();
// the implementation needs not do synchronization logic, because calls to it are surrounded by // the implementation needs not do synchronization logic, because calls to it are surrounded by
// PauseAndLock now // PauseAndLock now
void DoState(PointerWrap& p); void DoState(PointerWrap& p);