From e3b0a2c9bf3a73016d641788687aad8b49e04d97 Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Sat, 30 Mar 2013 14:02:30 +0100 Subject: [PATCH] Add an option to run the AX processing on the CPU thread. Fixes timing issues causing audio glitches on Wii, and should improve the overall stability of AX HLE. --- .../Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp | 43 +++++++++++++++---- .../Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h | 11 ++++- Source/Core/DolphinWX/Src/ConfigMain.cpp | 4 +- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp index 3675970917..ef7f2b61ca 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp @@ -18,27 +18,35 @@ #include "UCode_AX.h" #include "../../DSP.h" #include "FileUtil.h" +#include "ConfigManager.h" #define AX_GC #include "UCode_AX_Voice.h" CUCode_AX::CUCode_AX(DSPHLE* dsp_hle, u32 crc) : IUCode(dsp_hle, crc) + , m_work_available(false) , m_cmdlist_size(0) - , m_axthread(&SpawnAXThread, this) + , m_run_on_thread(SConfig::GetInstance().m_LocalCoreStartupParameter.bDSPThread) { WARN_LOG(DSPHLE, "Instantiating CUCode_AX: crc=%08x", crc); m_rMailHandler.PushMail(DSP_INIT); DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP); LoadResamplingCoefficients(); + + if (m_run_on_thread) + m_axthread = std::thread(SpawnAXThread, this); } CUCode_AX::~CUCode_AX() { - m_cmdlist_size = (u16)-1; // Special value to signal end - NotifyAXThread(); - m_axthread.join(); + if (m_run_on_thread) + { + m_cmdlist_size = (u16)-1; // Special value to signal end + NotifyAXThread(); + m_axthread.join(); + } m_rMailHandler.Clear(); } @@ -85,20 +93,32 @@ void CUCode_AX::AXThread() m_processing.lock(); HandleCommandList(); m_cmdlist_size = 0; - - // Signal end of processing - m_rMailHandler.PushMail(DSP_YIELD); - DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP); + SignalWorkEnd(); m_processing.unlock(); } } +void CUCode_AX::SignalWorkEnd() +{ + // Signal end of processing + m_rMailHandler.PushMail(DSP_YIELD); + DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP); +} + void CUCode_AX::NotifyAXThread() { std::unique_lock lk(m_cmdlist_mutex); m_cmdlist_cv.notify_one(); } +void CUCode_AX::StartWorking() +{ + if (m_run_on_thread) + NotifyAXThread(); + else + m_work_available = true; +} + void CUCode_AX::HandleCommandList() { // Temp variables for addresses computation @@ -620,6 +640,7 @@ void CUCode_AX::HandleMail(u32 mail) if (next_is_cmdlist) { CopyCmdList(mail, cmdlist_size); + StartWorking(); NotifyAXThread(); } else if (m_UploadSetupInProgress) @@ -688,6 +709,12 @@ void CUCode_AX::Update(int cycles) m_rMailHandler.PushMail(DSP_RESUME); DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP); } + else if (m_work_available) + { + HandleCommandList(); + m_cmdlist_size = 0; + SignalWorkEnd(); + } } void CUCode_AX::DoAXState(PointerWrap& p) diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h index 68248fef60..fbecac1990 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h @@ -102,11 +102,15 @@ protected: int m_samples_auxB_right[32 * 5]; int m_samples_auxB_surround[32 * 5]; + // This flag is set if there is anything to process. + bool m_work_available; + // Volatile because it's set by HandleMail and accessed in // HandleCommandList, which are running in two different threads. volatile u16 m_cmdlist[512]; volatile u32 m_cmdlist_size; + bool m_run_on_thread; std::thread m_axthread; // Sync objects @@ -130,13 +134,18 @@ protected: // versions of AX. AXMixControl ConvertMixerControl(u32 mixer_control); - // Send a notification to the AX thread to tell him a new cmdlist addr is + // Signal that we should start handling a command list. Dispatches to the + // AX thread if using a thread, else just sets a boolean flag. + void StartWorking(); + + // Send a notification to the AX thread to tell it a new cmdlist addr is // available for processing. void NotifyAXThread(); void AXThread(); virtual void HandleCommandList(); + void SignalWorkEnd(); void SetupProcessing(u32 init_addr); void DownloadAndMixWithVolume(u32 addr, u16 vol_main, u16 vol_auxa, u16 vol_auxb); diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index cbd780e6aa..c55b75f044 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -515,7 +515,7 @@ void CConfigMain::InitializeGUITooltips() InterfaceLang->SetToolTip(_("Change the language of the user interface.\nRequires restart.")); // Audio tooltips - DSPThread->SetToolTip(_("Run DSP LLE on a dedicated thread (not recommended).")); + DSPThread->SetToolTip(_("Run DSP HLE and LLE on a dedicated thread (not recommended: might cause audio glitches with HLE and freezes with LLE).")); BackendSelection->SetToolTip(_("Changing this will have no effect while the emulator is running!")); // Gamecube - Devices @@ -657,7 +657,7 @@ void CConfigMain::CreateGUIControls() // Audio page DSPEngine = new wxRadioBox(AudioPage, ID_DSPENGINE, _("DSP Emulator Engine"), wxDefaultPosition, wxDefaultSize, arrayStringFor_DSPEngine, 0, wxRA_SPECIFY_ROWS); - DSPThread = new wxCheckBox(AudioPage, ID_DSPTHREAD, _("DSP LLE on Thread")); + DSPThread = new wxCheckBox(AudioPage, ID_DSPTHREAD, _("DSP on Dedicated Thread")); DumpAudio = new wxCheckBox(AudioPage, ID_DUMP_AUDIO, _("Dump Audio"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); DPL2Decoder = new wxCheckBox(AudioPage, ID_DPL2DECODER, _("Dolby Pro Logic II decoder"));