Add an experimental sync to keep real time sync.
May help input, audio, and network related lag problems.
This commit is contained in:
parent
84ff3d6767
commit
29f2519861
3 changed files with 85 additions and 1 deletions
|
@ -265,6 +265,7 @@ static ConfigSetting generalSettings[] = {
|
|||
ConfigSetting("HomebrewStore", &g_Config.bHomebrewStore, false, false),
|
||||
ConfigSetting("CheckForNewVersion", &g_Config.bCheckForNewVersion, true),
|
||||
ConfigSetting("Language", &g_Config.sLanguageIni, &DefaultLangRegion),
|
||||
ConfigSetting("ForceLagSync", &g_Config.bForceLagSync, false),
|
||||
|
||||
ReportedConfigSetting("NumWorkerThreads", &g_Config.iNumWorkerThreads, &DefaultNumWorkers),
|
||||
ConfigSetting("EnableAutoLoad", &g_Config.bEnableAutoLoad, false),
|
||||
|
|
|
@ -83,6 +83,7 @@ public:
|
|||
bool bFastMemory;
|
||||
bool bJit;
|
||||
bool bCheckForNewVersion;
|
||||
bool bForceLagSync;
|
||||
|
||||
// Definitely cannot be changed while game is running.
|
||||
bool bSeparateCPUThread;
|
||||
|
|
|
@ -20,6 +20,22 @@
|
|||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
// TODO: Move this somewhere else, cleanup.
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#define NOMINMAX
|
||||
#include <winsock2.h>
|
||||
|
||||
static inline int usleep(long us) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = us;
|
||||
return select(0, NULL, NULL, NULL, &tv);
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: Move the relevant parts into common. Don't want the core
|
||||
// to be dependent on "native", I think. Or maybe should get rid of common
|
||||
// and move everything into native...
|
||||
|
@ -79,6 +95,10 @@ static bool framebufIsLatched;
|
|||
static int enterVblankEvent = -1;
|
||||
static int leaveVblankEvent = -1;
|
||||
static int afterFlipEvent = -1;
|
||||
static int lagSyncEvent = -1;
|
||||
|
||||
static double lastLagSync = 0.0;
|
||||
static bool lagSyncScheduled = false;
|
||||
|
||||
// hCount is computed now.
|
||||
static int vCount;
|
||||
|
@ -140,12 +160,21 @@ static int lastFlipsTooFrequent = 0;
|
|||
void hleEnterVblank(u64 userdata, int cyclesLate);
|
||||
void hleLeaveVblank(u64 userdata, int cyclesLate);
|
||||
void hleAfterFlip(u64 userdata, int cyclesLate);
|
||||
void hleLagSync(u64 userdata, int cyclesLate);
|
||||
|
||||
void __DisplayVblankBeginCallback(SceUID threadID, SceUID prevCallbackId);
|
||||
void __DisplayVblankEndCallback(SceUID threadID, SceUID prevCallbackId);
|
||||
int __DisplayGetFlipCount() { return actualFlips; }
|
||||
int __DisplayGetVCount() { return vCount; }
|
||||
|
||||
static void ScheduleLagSync() {
|
||||
lagSyncScheduled = g_Config.bForceLagSync;
|
||||
if (lagSyncScheduled) {
|
||||
CoreTiming::ScheduleEvent(msToCycles(1), lagSyncEvent, 0);
|
||||
lastLagSync = real_time_now();
|
||||
}
|
||||
}
|
||||
|
||||
void __DisplayInit() {
|
||||
gpuStats.Reset();
|
||||
hasSetMode = false;
|
||||
|
@ -168,6 +197,9 @@ void __DisplayInit() {
|
|||
leaveVblankEvent = CoreTiming::RegisterEvent("LeaveVBlank", &hleLeaveVblank);
|
||||
afterFlipEvent = CoreTiming::RegisterEvent("AfterFlip", &hleAfterFlip);
|
||||
|
||||
lagSyncEvent = CoreTiming::RegisterEvent("LagSync", &hleLagSync);
|
||||
ScheduleLagSync();
|
||||
|
||||
CoreTiming::ScheduleEvent(msToCycles(frameMs - vblankMs), enterVblankEvent, 0);
|
||||
isVblank = 0;
|
||||
vCount = 0;
|
||||
|
@ -189,7 +221,7 @@ void __DisplayInit() {
|
|||
}
|
||||
|
||||
void __DisplayDoState(PointerWrap &p) {
|
||||
auto s = p.Section("sceDisplay", 1, 4);
|
||||
auto s = p.Section("sceDisplay", 1, 5);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
|
@ -226,6 +258,19 @@ void __DisplayDoState(PointerWrap &p) {
|
|||
p.Do(afterFlipEvent);
|
||||
CoreTiming::RestoreRegisterEvent(afterFlipEvent, "AfterFlip", &hleAfterFlip);
|
||||
|
||||
if (s >= 5) {
|
||||
p.Do(lagSyncEvent);
|
||||
p.Do(lagSyncScheduled);
|
||||
CoreTiming::RestoreRegisterEvent(lagSyncEvent, "LagSync", &hleLagSync);
|
||||
lastLagSync = real_time_now();
|
||||
if (lagSyncScheduled != g_Config.bForceLagSync) {
|
||||
ScheduleLagSync();
|
||||
}
|
||||
} else {
|
||||
lagSyncEvent = CoreTiming::RegisterEvent("LagSync", &hleLagSync);
|
||||
ScheduleLagSync();
|
||||
}
|
||||
|
||||
p.Do(gstate);
|
||||
gstate_c.DoState(p);
|
||||
#ifndef _XBOX
|
||||
|
@ -621,6 +666,11 @@ void hleEnterVblank(u64 userdata, int cyclesLate) {
|
|||
void hleAfterFlip(u64 userdata, int cyclesLate)
|
||||
{
|
||||
gpu->BeginFrame(); // doesn't really matter if begin or end of frame.
|
||||
|
||||
// This seems like as good a time as any to check if the config changed.
|
||||
if (lagSyncScheduled != g_Config.bForceLagSync) {
|
||||
ScheduleLagSync();
|
||||
}
|
||||
}
|
||||
|
||||
void hleLeaveVblank(u64 userdata, int cyclesLate) {
|
||||
|
@ -632,6 +682,38 @@ void hleLeaveVblank(u64 userdata, int cyclesLate) {
|
|||
__DisplayFireVblank();
|
||||
}
|
||||
|
||||
void hleLagSync(u64 userdata, int cyclesLate) {
|
||||
// The goal here is to prevent network, audio, and input lag from the real world.
|
||||
// Our normal timing is very "stop and go". This is efficient, but causes real world lag.
|
||||
// This event (optionally) runs every 1ms to sync with the real world.
|
||||
|
||||
if (PSP_CoreParameter().unthrottle) {
|
||||
lagSyncScheduled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
float scale = 1.0f;
|
||||
if (PSP_CoreParameter().fpsLimit == FPS_LIMIT_CUSTOM) {
|
||||
if (g_Config.iFpsLimit == 0) {
|
||||
lagSyncScheduled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
scale = g_Config.iFpsLimit / 60.0f;
|
||||
}
|
||||
|
||||
// TODO: Smarter, adaptive? Account for cyclesLate? Let's just try this for now.
|
||||
const double goal = lastLagSync + (scale / 1000.0f);
|
||||
time_update();
|
||||
while (time_now_d() < goal) {
|
||||
const double left = goal - time_now_d();
|
||||
usleep((long)(left * 1000000));
|
||||
time_update();
|
||||
}
|
||||
|
||||
ScheduleLagSync();
|
||||
}
|
||||
|
||||
u32 sceDisplayIsVblank() {
|
||||
DEBUG_LOG(SCEDISPLAY,"%i=sceDisplayIsVblank()",isVblank);
|
||||
return isVblank;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue