mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Add a setting to launch a separate CPU thread.
This commit is contained in:
parent
e03acc4c58
commit
e7c7c5b3db
6 changed files with 190 additions and 51 deletions
|
@ -89,6 +89,7 @@ void Config::Load(const char *iniFileName)
|
|||
#else
|
||||
cpu->Get("Jit", &bJit, true);
|
||||
#endif
|
||||
cpu->Get("UseCPUThread", &bUseCPUThread, false);
|
||||
cpu->Get("FastMemory", &bFastMemory, false);
|
||||
cpu->Get("CPUSpeed", &iLockedCPUSpeed, false);
|
||||
|
||||
|
@ -226,6 +227,7 @@ void Config::Save()
|
|||
|
||||
IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU");
|
||||
cpu->Set("Jit", bJit);
|
||||
cpu->Set("UseCPUThread", bUseCPUThread);
|
||||
cpu->Set("FastMemory", bFastMemory);
|
||||
cpu->Set("CPUSpeed", iLockedCPUSpeed);
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ public:
|
|||
bool bIgnoreBadMemAccess;
|
||||
bool bFastMemory;
|
||||
bool bJit;
|
||||
bool bUseCPUThread;
|
||||
int iLockedCPUSpeed;
|
||||
bool bAutoSaveSymbolMap;
|
||||
std::string sReportHost;
|
||||
|
|
|
@ -40,6 +40,7 @@ struct CoreParameter
|
|||
|
||||
std::string fileToStart;
|
||||
std::string mountIso; // If non-empty, and fileToStart is an ELF or PBP, will mount this ISO in the background.
|
||||
std::string errorString;
|
||||
|
||||
bool startPaused;
|
||||
bool disableG3Dlog;
|
||||
|
|
201
Core/System.cpp
201
Core/System.cpp
|
@ -39,31 +39,73 @@
|
|||
#include "Core/PSPLoaders.h"
|
||||
#include "Core/ELF/ParamSFO.h"
|
||||
#include "Core/SaveState.h"
|
||||
#include "Common/StdConditionVariable.h"
|
||||
#include "Common/Thread.h"
|
||||
#include "Common/StdThread.h"
|
||||
#include "Common/LogManager.h"
|
||||
|
||||
#include "GPU/GPUState.h"
|
||||
#include "GPU/GPUInterface.h"
|
||||
|
||||
enum CPUThreadState {
|
||||
CPU_THREAD_NOT_RUNNING,
|
||||
CPU_THREAD_PENDING,
|
||||
CPU_THREAD_STARTING,
|
||||
CPU_THREAD_RUNNING,
|
||||
CPU_THREAD_SHUTDOWN,
|
||||
|
||||
CPU_THREAD_EXECUTE,
|
||||
};
|
||||
|
||||
MetaFileSystem pspFileSystem;
|
||||
ParamSFOData g_paramSFO;
|
||||
GlobalUIState globalUIState;
|
||||
static CoreParameter coreParameter;
|
||||
static PSPMixer *mixer;
|
||||
static std::thread *cpuThread = NULL;
|
||||
static std::mutex cpuThreadLock;
|
||||
static std::condition_variable cpuThreadCond;
|
||||
static u64 cpuThreadUntil;
|
||||
|
||||
// This can be read and written from ANYWHERE.
|
||||
volatile CoreState coreState = CORE_STEPPING;
|
||||
// Note: intentionally not used for CORE_NEXTFRAME.
|
||||
volatile bool coreStatePending = false;
|
||||
static volatile CPUThreadState cpuThreadState = CPU_THREAD_NOT_RUNNING;
|
||||
|
||||
void Core_UpdateState(CoreState newState)
|
||||
{
|
||||
if ((coreState == CORE_RUNNING || coreState == CORE_NEXTFRAME) && newState != CORE_RUNNING)
|
||||
coreStatePending = true;
|
||||
coreState = newState;
|
||||
bool CPU_NextState(CPUThreadState from, CPUThreadState to) {
|
||||
if (cpuThreadState == from) {
|
||||
cpuThreadState = to;
|
||||
cpuThreadCond.notify_all();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PSP_Init(const CoreParameter &coreParam, std::string *error_string)
|
||||
{
|
||||
INFO_LOG(HLE, "PPSSPP %s", PPSSPP_GIT_VERSION);
|
||||
void CPU_SetState(CPUThreadState to) {
|
||||
cpuThreadState = to;
|
||||
cpuThreadCond.notify_all();
|
||||
}
|
||||
|
||||
coreParameter = coreParam;
|
||||
bool CPU_IsReady() {
|
||||
return cpuThreadState == CPU_THREAD_RUNNING || cpuThreadState == CPU_THREAD_NOT_RUNNING;
|
||||
}
|
||||
|
||||
bool CPU_IsShutdown() {
|
||||
return cpuThreadState == CPU_THREAD_NOT_RUNNING;
|
||||
}
|
||||
|
||||
bool CPU_HasPendingAction() {
|
||||
return cpuThreadState != CPU_THREAD_RUNNING;
|
||||
}
|
||||
|
||||
void CPU_WaitStatus(bool (*pred)()) {
|
||||
std::unique_lock<std::mutex> uniqueLock(cpuThreadLock);
|
||||
cpuThreadCond.wait(uniqueLock, pred);
|
||||
}
|
||||
|
||||
void CPU_Init() {
|
||||
currentCPU = &mipsr4k;
|
||||
numCPUs = 1;
|
||||
|
||||
|
@ -73,11 +115,12 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string)
|
|||
g_RemasterMode = false;
|
||||
g_DoubleTextureCoordinates = false;
|
||||
|
||||
std::string filename = coreParam.fileToStart;
|
||||
std::string filename = coreParameter.fileToStart;
|
||||
EmuFileType type = Identify_File(filename);
|
||||
|
||||
if(type == FILETYPE_PSP_ISO || type == FILETYPE_PSP_ISO_NP || type == FILETYPE_PSP_DISC_DIRECTORY)
|
||||
if (type == FILETYPE_PSP_ISO || type == FILETYPE_PSP_ISO_NP || type == FILETYPE_PSP_DISC_DIRECTORY) {
|
||||
InitMemoryForGameISO(filename);
|
||||
}
|
||||
|
||||
Memory::Init();
|
||||
mipsr4k.Reset();
|
||||
|
@ -85,14 +128,12 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string)
|
|||
|
||||
host->AttemptLoadSymbolMap();
|
||||
|
||||
if (coreParameter.enableSound)
|
||||
{
|
||||
if (coreParameter.enableSound) {
|
||||
mixer = new PSPMixer();
|
||||
host->InitSound(mixer);
|
||||
}
|
||||
|
||||
if (coreParameter.disableG3Dlog)
|
||||
{
|
||||
if (coreParameter.disableG3Dlog) {
|
||||
LogManager::GetInstance()->SetEnable(LogTypes::G3D, false);
|
||||
}
|
||||
|
||||
|
@ -104,7 +145,7 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string)
|
|||
// TODO: Check Game INI here for settings, patches and cheats, and modify coreParameter accordingly
|
||||
|
||||
// Why did we check for CORE_POWERDOWN here?
|
||||
if (!LoadFile(filename, error_string)) { // || coreState == CORE_POWERDOWN) {
|
||||
if (!LoadFile(filename, &coreParameter.errorString)) {
|
||||
pspFileSystem.Shutdown();
|
||||
CoreTiming::Shutdown();
|
||||
__KernelShutdown();
|
||||
|
@ -112,36 +153,27 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string)
|
|||
host->ShutdownSound();
|
||||
Memory::Shutdown();
|
||||
coreParameter.fileToStart = "";
|
||||
return false;
|
||||
CPU_SetState(CPU_THREAD_NOT_RUNNING);
|
||||
return;
|
||||
}
|
||||
|
||||
if (coreParam.updateRecent)
|
||||
if (coreParameter.updateRecent) {
|
||||
g_Config.AddRecent(filename);
|
||||
}
|
||||
|
||||
// Setup JIT here.
|
||||
if (coreParameter.startPaused)
|
||||
coreState = CORE_STEPPING;
|
||||
else
|
||||
coreState = CORE_RUNNING;
|
||||
return true;
|
||||
coreState = coreParameter.startPaused ? CORE_STEPPING : CORE_RUNNING;
|
||||
}
|
||||
|
||||
bool PSP_IsInited()
|
||||
{
|
||||
return currentCPU != 0;
|
||||
}
|
||||
|
||||
void PSP_Shutdown()
|
||||
{
|
||||
void CPU_Shutdown() {
|
||||
pspFileSystem.Shutdown();
|
||||
|
||||
CoreTiming::Shutdown();
|
||||
|
||||
if (g_Config.bAutoSaveSymbolMap)
|
||||
if (g_Config.bAutoSaveSymbolMap) {
|
||||
host->SaveSymbolMap();
|
||||
}
|
||||
|
||||
if (coreParameter.enableSound)
|
||||
{
|
||||
if (coreParameter.enableSound) {
|
||||
host->ShutdownSound();
|
||||
mixer = 0; // deleted in ShutdownSound
|
||||
}
|
||||
|
@ -151,17 +183,112 @@ void PSP_Shutdown()
|
|||
currentCPU = 0;
|
||||
}
|
||||
|
||||
void CPU_RunLoop() {
|
||||
Common::SetCurrentThreadName("CPUThread");
|
||||
if (!CPU_NextState(CPU_THREAD_PENDING, CPU_THREAD_STARTING)) {
|
||||
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(&CPU_HasPendingAction);
|
||||
switch (cpuThreadState) {
|
||||
case CPU_THREAD_EXECUTE:
|
||||
mipsr4k.RunLoopUntil(cpuThreadUntil);
|
||||
CPU_NextState(CPU_THREAD_EXECUTE, CPU_THREAD_RUNNING);
|
||||
break;
|
||||
|
||||
// These are fine, just keep looping.
|
||||
case CPU_THREAD_RUNNING:
|
||||
case CPU_THREAD_SHUTDOWN:
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG(CPU, "CPU thread in unexpected state: %d", cpuThreadState);
|
||||
// Begin shutdown, otherwise we'd just spin on this bad state.
|
||||
cpuThreadState = CPU_THREAD_SHUTDOWN;
|
||||
cpuThreadCond.notify_all();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (coreState != CORE_ERROR) {
|
||||
coreState = CORE_POWERDOWN;
|
||||
}
|
||||
|
||||
CPU_Shutdown();
|
||||
CPU_SetState(CPU_THREAD_NOT_RUNNING);
|
||||
}
|
||||
|
||||
void Core_UpdateState(CoreState newState) {
|
||||
if ((coreState == CORE_RUNNING || coreState == CORE_NEXTFRAME) && newState != CORE_RUNNING)
|
||||
coreStatePending = true;
|
||||
coreState = newState;
|
||||
}
|
||||
|
||||
bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) {
|
||||
INFO_LOG(HLE, "PPSSPP %s", PPSSPP_GIT_VERSION);
|
||||
|
||||
coreParameter = coreParam;
|
||||
coreParameter.errorString = "";
|
||||
|
||||
if (g_Config.bUseCPUThread) {
|
||||
CPU_SetState(CPU_THREAD_PENDING);
|
||||
cpuThread = new std::thread(&CPU_RunLoop);
|
||||
CPU_WaitStatus(&CPU_IsReady);
|
||||
} else {
|
||||
CPU_Init();
|
||||
}
|
||||
|
||||
bool success = coreParameter.fileToStart != "";
|
||||
*error_string = coreParam.errorString;
|
||||
if (success) {
|
||||
GPU_Init();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool PSP_IsInited() {
|
||||
return currentCPU != 0;
|
||||
}
|
||||
|
||||
void PSP_Shutdown() {
|
||||
if (coreState == CORE_RUNNING)
|
||||
coreState = CORE_ERROR;
|
||||
if (g_Config.bUseCPUThread) {
|
||||
CPU_SetState(CPU_THREAD_SHUTDOWN);
|
||||
CPU_WaitStatus(&CPU_IsShutdown);
|
||||
} else {
|
||||
CPU_Shutdown();
|
||||
}
|
||||
GPU_Shutdown();
|
||||
}
|
||||
|
||||
void PSP_RunLoopUntil(u64 globalticks) {
|
||||
SaveState::Process();
|
||||
mipsr4k.RunLoopUntil(globalticks);
|
||||
|
||||
if (g_Config.bUseCPUThread) {
|
||||
cpuThreadUntil = globalticks;
|
||||
if (CPU_NextState(CPU_THREAD_RUNNING, CPU_THREAD_EXECUTE)) {
|
||||
// TODO: Run GPU here.
|
||||
CPU_WaitStatus(&CPU_IsReady);
|
||||
} else {
|
||||
ERROR_LOG(CPU, "Unable to execute CPU run loop, unexpected state: %d", cpuThreadState);
|
||||
}
|
||||
} else {
|
||||
mipsr4k.RunLoopUntil(globalticks);
|
||||
}
|
||||
}
|
||||
|
||||
void PSP_RunLoopFor(int cycles) {
|
||||
PSP_RunLoopUntil(CoreTiming::GetTicks() + cycles);
|
||||
}
|
||||
|
||||
CoreParameter &PSP_CoreParameter()
|
||||
{
|
||||
CoreParameter &PSP_CoreParameter() {
|
||||
return coreParameter;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,25 @@ GPUStateCache gstate_c;
|
|||
GPUInterface *gpu;
|
||||
GPUStatistics gpuStats;
|
||||
|
||||
void GPU_Init() {
|
||||
switch (PSP_CoreParameter().gpuCore) {
|
||||
case GPU_NULL:
|
||||
gpu = new NullGPU();
|
||||
break;
|
||||
case GPU_GLES:
|
||||
gpu = new GLES_GPU();
|
||||
break;
|
||||
case GPU_SOFTWARE:
|
||||
gpu = new NullGPU();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_Shutdown() {
|
||||
delete gpu;
|
||||
gpu = 0;
|
||||
}
|
||||
|
||||
void InitGfxState()
|
||||
{
|
||||
memset(&gstate, 0, sizeof(gstate));
|
||||
|
@ -56,24 +75,10 @@ void InitGfxState()
|
|||
for (int i = 0; i < 8; i++) {
|
||||
memcpy(gstate.boneMatrix + i * 12, identity4x3, 12 * sizeof(float));
|
||||
}
|
||||
|
||||
switch (PSP_CoreParameter().gpuCore) {
|
||||
case GPU_NULL:
|
||||
gpu = new NullGPU();
|
||||
break;
|
||||
case GPU_GLES:
|
||||
gpu = new GLES_GPU();
|
||||
break;
|
||||
case GPU_SOFTWARE:
|
||||
gpu = new NullGPU();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ShutdownGfxState()
|
||||
{
|
||||
delete gpu;
|
||||
gpu = NULL;
|
||||
}
|
||||
|
||||
// When you have changed state outside the psp gfx core,
|
||||
|
|
|
@ -427,6 +427,9 @@ struct GPUStatistics {
|
|||
int numFBOs;
|
||||
};
|
||||
|
||||
void GPU_Init();
|
||||
void GPU_Shutdown();
|
||||
|
||||
void InitGfxState();
|
||||
void ShutdownGfxState();
|
||||
void ReapplyGfxState();
|
||||
|
|
Loading…
Add table
Reference in a new issue