From b6308bab4f92376034360a15dfa4c756e9cafe26 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Tue, 24 May 2022 00:20:29 +1000 Subject: [PATCH] Qt: Initialize COM ourselves on EmuThread If we don't, SDL initializes it first in STA mode, which prevents MT mode from being used, which prevents us from using XAudio2. --- pcsx2-qt/EmuThread.cpp | 4 +++- pcsx2-qt/QtHost.cpp | 6 ++---- pcsx2/VMManager.cpp | 23 +++++++++++++++++++++++ pcsx2/VMManager.h | 3 +++ 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/pcsx2-qt/EmuThread.cpp b/pcsx2-qt/EmuThread.cpp index 1bcf3e0537..6ffe480ec1 100644 --- a/pcsx2-qt/EmuThread.cpp +++ b/pcsx2-qt/EmuThread.cpp @@ -228,7 +228,8 @@ void EmuThread::run() m_event_loop = new QEventLoop(); m_started_semaphore.release(); - if (!VMManager::Internal::InitializeMemory()) + // neither of these should ever fail. + if (!VMManager::Internal::InitializeGlobals() || !VMManager::Internal::InitializeMemory()) pxFailRel("Failed to allocate memory map"); // we need input sources ready for binding @@ -252,6 +253,7 @@ void EmuThread::run() InputManager::CloseSources(); VMManager::WaitForSaveStateFlush(); VMManager::Internal::ReleaseMemory(); + VMManager::Internal::ReleaseGlobals(); PerformanceMetrics::SetCPUThread(Threading::ThreadHandle()); moveToThread(m_ui_thread); deleteLater(); diff --git a/pcsx2-qt/QtHost.cpp b/pcsx2-qt/QtHost.cpp index d579a62070..c411cff839 100644 --- a/pcsx2-qt/QtHost.cpp +++ b/pcsx2-qt/QtHost.cpp @@ -86,13 +86,11 @@ bool QtHost::Initialize() if (!InitializeConfig()) { - Console.WriteLn("Failed to initialize config."); + // NOTE: No point translating this, because no config means the language won't be loaded anyway. + QMessageBox::critical(nullptr, QStringLiteral("Error"), QStringLiteral("Failed to initialize config.")); return false; } - if (!VMManager::Internal::InitializeGlobals()) - return false; - HookSignals(); return true; } diff --git a/pcsx2/VMManager.cpp b/pcsx2/VMManager.cpp index 82dd1fdf02..3b6e39b279 100644 --- a/pcsx2/VMManager.cpp +++ b/pcsx2/VMManager.cpp @@ -62,6 +62,10 @@ #include "common/emitter/x86_intrin.h" #endif +#ifdef _WIN32 +#include "common/RedtapeWindows.h" +#endif + namespace VMManager { static void LoadSettings(); @@ -187,6 +191,18 @@ std::string VMManager::GetGameName() bool VMManager::Internal::InitializeGlobals() { + // On Win32, we have a bunch of things which use COM (e.g. SDL, XAudio2, etc). + // We need to initialize COM first, before anything else does, because otherwise they might + // initialize it in single-threaded/apartment mode, which can't be changed to multithreaded. +#ifdef _WIN32 + HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); + if (FAILED(hr)) + { + Host::ReportErrorAsync("Error", fmt::format("CoInitializeEx() failed: {:08X}", hr)); + return false; + } +#endif + x86caps.Identify(); x86caps.CountCores(); x86caps.SIMD_EstablishMXCSRmask(); @@ -196,6 +212,13 @@ bool VMManager::Internal::InitializeGlobals() return true; } +void VMManager::Internal::ReleaseGlobals() +{ +#ifdef _WIN32 + CoUninitialize(); +#endif +} + bool VMManager::Internal::InitializeMemory() { pxAssert(!s_vm_memory && !s_cpu_provider_pack); diff --git a/pcsx2/VMManager.h b/pcsx2/VMManager.h index df29926d54..227d980389 100644 --- a/pcsx2/VMManager.h +++ b/pcsx2/VMManager.h @@ -153,6 +153,9 @@ namespace VMManager /// Performs early global initialization. bool InitializeGlobals(); + /// Releases resources allocated in InitializeGlobals(). + void ReleaseGlobals(); + /// Reserves memory for the virtual machines. bool InitializeMemory();