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.

This commit is contained in:
Pierre Bourdon 2013-03-30 14:02:30 +01:00
parent c271082ec5
commit e3b0a2c9bf
3 changed files with 47 additions and 11 deletions

View File

@ -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<std::mutex> 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)

View File

@ -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);

View File

@ -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"));