Merge pull request #7202 from unknownbrackets/cpu-thread

Allow switching cpu thread on/off ingame
This commit is contained in:
Henrik Rydgård 2014-12-24 19:15:51 +01:00
commit f74add91e2
6 changed files with 47 additions and 15 deletions

View File

@ -63,8 +63,10 @@ enum CPUThreadState {
CPU_THREAD_STARTING,
CPU_THREAD_RUNNING,
CPU_THREAD_SHUTDOWN,
CPU_THREAD_QUIT,
CPU_THREAD_EXECUTE,
CPU_THREAD_RESUME,
};
MetaFileSystem pspFileSystem;
@ -73,7 +75,7 @@ static GlobalUIState globalUIState;
static CoreParameter coreParameter;
static FileLoader *loadedFile;
static PSPMixer *mixer;
static std::thread *cpuThread = NULL;
static std::thread *cpuThread = nullptr;
static std::thread::id cpuThreadID;
static recursive_mutex cpuThreadLock;
static condition_variable cpuThreadCond;
@ -110,7 +112,7 @@ void Audio_Init() {
}
bool IsOnSeparateCPUThread() {
if (cpuThread != NULL) {
if (cpuThread != nullptr) {
return cpuThreadID == std::this_thread::get_id();
} else {
return false;
@ -269,14 +271,14 @@ void CPU_RunLoop() {
setCurrentThreadName("CPU");
FPU_SetFastMode();
if (!CPU_NextState(CPU_THREAD_PENDING, CPU_THREAD_STARTING)) {
if (CPU_NextState(CPU_THREAD_PENDING, CPU_THREAD_STARTING)) {
CPU_Init();
CPU_NextState(CPU_THREAD_STARTING, CPU_THREAD_RUNNING);
} else if (!CPU_NextState(CPU_THREAD_RESUME, CPU_THREAD_RUNNING)) {
ERROR_LOG(CPU, "CPU thread in unexpected state: %d", cpuThreadState);
return;
}
CPU_Init();
CPU_NextState(CPU_THREAD_STARTING, CPU_THREAD_RUNNING);
while (cpuThreadState != CPU_THREAD_SHUTDOWN)
{
CPU_WaitStatus(cpuThreadCond, &CPU_HasPendingAction);
@ -292,6 +294,11 @@ void CPU_RunLoop() {
case CPU_THREAD_SHUTDOWN:
break;
case CPU_THREAD_QUIT:
// Just leave the thread, CPU is switching off thread.
CPU_SetState(CPU_THREAD_NOT_RUNNING);
return;
default:
ERROR_LOG(CPU, "CPU thread in unexpected state: %d", cpuThreadState);
// Begin shutdown, otherwise we'd just spin on this bad state.
@ -426,7 +433,7 @@ void PSP_Shutdown() {
if (coreState == CORE_RUNNING)
Core_UpdateState(CORE_ERROR);
Core_NotifyShutdown();
if (cpuThread != NULL) {
if (cpuThread != nullptr) {
CPU_NextStateNot(CPU_THREAD_NOT_RUNNING, CPU_THREAD_SHUTDOWN);
CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsShutdown);
delete cpuThread;
@ -451,7 +458,31 @@ void PSP_RunLoopUntil(u64 globalticks) {
return;
}
if (cpuThread != NULL) {
// Switch the CPU thread on or off, as the case may be.
bool useCPUThread = g_Config.bSeparateCPUThread;
if (useCPUThread && cpuThread == nullptr) {
// Need to start the cpu thread.
Core_ListenShutdown(System_Wake);
CPU_SetState(CPU_THREAD_RESUME);
cpuThread = new std::thread(&CPU_RunLoop);
cpuThreadID = cpuThread->get_id();
cpuThread->detach();
if (gpu) {
gpu->SetThreadEnabled(true);
}
CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsReady);
} else if (!useCPUThread && cpuThread != nullptr) {
CPU_SetState(CPU_THREAD_QUIT);
CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsShutdown);
delete cpuThread;
cpuThread = nullptr;
cpuThreadID = std::thread::id();
if (gpu) {
gpu->SetThreadEnabled(false);
}
}
if (cpuThread != nullptr) {
// Tell the gpu a new frame is about to begin, before we start the CPU.
gpu->SyncBeginFrame();

View File

@ -543,7 +543,7 @@ void DIRECTX9_GPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferForma
bool DIRECTX9_GPU::FramebufferDirty() {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
if (g_Config.bSeparateCPUThread) {
if (ThreadEnabled()) {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
ScheduleEvent(GPU_EVENT_PROCESS_QUEUE);
// Allow it to process fully before deciding if it's dirty.
@ -559,7 +559,7 @@ bool DIRECTX9_GPU::FramebufferDirty() {
}
bool DIRECTX9_GPU::FramebufferReallyDirty() {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
if (g_Config.bSeparateCPUThread) {
if (ThreadEnabled()) {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
ScheduleEvent(GPU_EVENT_PROCESS_QUEUE);
// Allow it to process fully before deciding if it's dirty.

View File

@ -615,7 +615,7 @@ void GLES_GPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat fo
}
bool GLES_GPU::FramebufferDirty() {
if (g_Config.bSeparateCPUThread) {
if (ThreadEnabled()) {
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
@ -630,7 +630,7 @@ bool GLES_GPU::FramebufferDirty() {
}
bool GLES_GPU::FramebufferReallyDirty() {
if (g_Config.bSeparateCPUThread) {
if (ThreadEnabled()) {
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}

View File

@ -69,7 +69,7 @@ bool GPUCommon::BusyDrawing() {
}
u32 GPUCommon::DrawSync(int mode) {
if (g_Config.bSeparateCPUThread) {
if (ThreadEnabled()) {
// Sync first, because the CPU is usually faster than the emulated GPU.
SyncThread();
}
@ -124,7 +124,7 @@ void GPUCommon::CheckDrawSync() {
}
int GPUCommon::ListSync(int listid, int mode) {
if (g_Config.bSeparateCPUThread) {
if (ThreadEnabled()) {
// Sync first, because the CPU is usually faster than the emulated GPU.
SyncThread();
}

View File

@ -275,6 +275,7 @@ public:
virtual bool FramebufferDirty() = 0;
virtual bool FramebufferReallyDirty() = 0;
virtual bool BusyDrawing() = 0;
virtual void SetThreadEnabled(bool threadEnabled) = 0;
// If any jit is being used inside the GPU.
virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) = 0;

View File

@ -390,7 +390,7 @@ void GameSettingsScreen::CreateViews() {
systemSettings->Add(new ItemHeader(s->T("Emulation")));
systemSettings->Add(new CheckBox(&g_Config.bFastMemory, s->T("Fast Memory", "Fast Memory (Unstable)")))->OnClick.Handle(this, &GameSettingsScreen::OnJitAffectingSetting);
systemSettings->Add(new CheckBox(&g_Config.bSeparateCPUThread, s->T("Multithreaded (experimental)")))->SetEnabled(!PSP_IsInited());
systemSettings->Add(new CheckBox(&g_Config.bSeparateCPUThread, s->T("Multithreaded (experimental)")));
systemSettings->Add(new CheckBox(&g_Config.bSeparateIOThread, s->T("I/O on thread (experimental)")))->SetEnabled(!PSP_IsInited());
systemSettings->Add(new CheckBox(&g_Config.bForceLagSync, s->T("Force real clock sync (slower, less lag)")));
systemSettings->Add(new PopupSliderChoice(&g_Config.iLockedCPUSpeed, 0, 1000, s->T("Change CPU Clock", "Change CPU Clock (0 = default) (unstable)"), screenManager()));