mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Use a timer to keep gpu/cpu in sync periodically.
Fixes Diva Extend demo, at least, losing FPS.
This commit is contained in:
parent
7c4d273879
commit
cf7c718706
4 changed files with 48 additions and 1 deletions
|
@ -40,6 +40,11 @@ struct GeInterruptData
|
|||
static std::list<GeInterruptData> ge_pending_cb;
|
||||
static int geSyncEvent;
|
||||
static int geInterruptEvent;
|
||||
static int geCycleEvent;
|
||||
|
||||
// Let's try updating 10 times per vblank.
|
||||
const int geIntervalUs = 1000000 / (60 * 10);
|
||||
const int geBehindThresholdUs = 1000000 / (60 * 10);
|
||||
|
||||
class GeIntrHandler : public IntrHandler
|
||||
{
|
||||
|
@ -162,6 +167,20 @@ void __GeExecuteInterrupt(u64 userdata, int cyclesLate)
|
|||
__TriggerInterrupt(PSP_INTR_IMMEDIATE, PSP_GE_INTR, PSP_INTR_SUB_NONE);
|
||||
}
|
||||
|
||||
void __GeCheckCycles(u64 userdata, int cyclesLate)
|
||||
{
|
||||
u64 geTicks = gpu->GetTickEstimate();
|
||||
if (geTicks != 0)
|
||||
{
|
||||
if (CoreTiming::GetTicks() > geTicks + usToCycles(geBehindThresholdUs)) {
|
||||
u64 diff = CoreTiming::GetTicks() - geTicks;
|
||||
gpu->SyncThread();
|
||||
CoreTiming::Advance();
|
||||
}
|
||||
}
|
||||
CoreTiming::ScheduleEvent(usToCycles(geIntervalUs), geCycleEvent, 0);
|
||||
}
|
||||
|
||||
void __GeInit()
|
||||
{
|
||||
memset(&ge_used_callbacks, 0, sizeof(ge_used_callbacks));
|
||||
|
@ -170,6 +189,12 @@ void __GeInit()
|
|||
|
||||
geSyncEvent = CoreTiming::RegisterEvent("GeSyncEvent", &__GeExecuteSync);
|
||||
geInterruptEvent = CoreTiming::RegisterEvent("GeInterruptEvent", &__GeExecuteInterrupt);
|
||||
geCycleEvent = CoreTiming::RegisterEvent("GeCycleEvent", &__GeCheckCycles);
|
||||
|
||||
// When we're using separate CPU/GPU threads, we need to keep them in sync.
|
||||
if (IsOnSeparateCPUThread()) {
|
||||
CoreTiming::ScheduleEvent(usToCycles(geIntervalUs), geCycleEvent, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void __GeDoState(PointerWrap &p)
|
||||
|
@ -182,6 +207,8 @@ void __GeDoState(PointerWrap &p)
|
|||
CoreTiming::RestoreRegisterEvent(geSyncEvent, "GeSyncEvent", &__GeExecuteSync);
|
||||
p.Do(geInterruptEvent);
|
||||
CoreTiming::RestoreRegisterEvent(geInterruptEvent, "GeInterruptEvent", &__GeExecuteInterrupt);
|
||||
p.Do(geCycleEvent);
|
||||
CoreTiming::RestoreRegisterEvent(geCycleEvent, "GeCycleEvent", &__GeCheckCycles);
|
||||
|
||||
// Everything else is done in sceDisplay.
|
||||
p.DoMarker("sceGe");
|
||||
|
|
|
@ -20,7 +20,8 @@ GPUCommon::GPUCommon() :
|
|||
busyTicks(0),
|
||||
dumpNextFrame_(false),
|
||||
dumpThisFrame_(false),
|
||||
interruptsEnabled_(true)
|
||||
interruptsEnabled_(true),
|
||||
curTickEst_(0)
|
||||
{
|
||||
memset(dls, 0, sizeof(dls));
|
||||
for (int i = 0; i < DisplayListMaxCount; ++i) {
|
||||
|
@ -579,6 +580,7 @@ bool GPUCommon::ProcessDLQueue() {
|
|||
void GPUCommon::ProcessDLQueueInternal() {
|
||||
startingTicks = CoreTiming::GetTicks();
|
||||
cyclesExecuted = 0;
|
||||
UpdateTickEstimate(std::max(busyTicks, startingTicks + cyclesExecuted));
|
||||
|
||||
if (startingTicks < busyTicks) {
|
||||
DEBUG_LOG(HLE, "Can't execute a list yet, still busy for %lld ticks", busyTicks - startingTicks);
|
||||
|
@ -594,6 +596,7 @@ void GPUCommon::ProcessDLQueueInternal() {
|
|||
easy_guard guard(listLock);
|
||||
// At the end, we can remove it from the queue and continue.
|
||||
dlQueue.erase(std::remove(dlQueue.begin(), dlQueue.end(), listIndex), dlQueue.end());
|
||||
UpdateTickEstimate(std::max(busyTicks, startingTicks + cyclesExecuted));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -603,6 +606,8 @@ void GPUCommon::ProcessDLQueueInternal() {
|
|||
drawCompleteTicks = startingTicks + cyclesExecuted;
|
||||
busyTicks = std::max(busyTicks, drawCompleteTicks);
|
||||
__GeTriggerSync(WAITTYPE_GEDRAWSYNC, 1, drawCompleteTicks);
|
||||
// Since the event is in CoreTiming, we're in sync. Just set 0 now.
|
||||
UpdateTickEstimate(0);
|
||||
}
|
||||
|
||||
void GPUCommon::PreExecuteOp(u32 op, u32 diff) {
|
||||
|
|
|
@ -36,6 +36,11 @@ public:
|
|||
virtual u32 Break(int mode);
|
||||
virtual void ReapplyGfxState();
|
||||
|
||||
virtual u64 GetTickEstimate() {
|
||||
lock_guard guard(curTickEstLock_);
|
||||
return curTickEst_;
|
||||
}
|
||||
|
||||
protected:
|
||||
// To avoid virtual calls to PreExecuteOp().
|
||||
virtual void FastRunLoop(DisplayList &list) = 0;
|
||||
|
@ -86,6 +91,15 @@ protected:
|
|||
bool dumpThisFrame_;
|
||||
bool interruptsEnabled_;
|
||||
|
||||
// For CPU/GPU sync.
|
||||
volatile u64 curTickEst_;
|
||||
recursive_mutex curTickEstLock_;
|
||||
|
||||
virtual void UpdateTickEstimate(u64 value) {
|
||||
lock_guard guard(curTickEstLock_);
|
||||
curTickEst_ = value;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual DisplayList* getList(int listid)
|
||||
{
|
||||
|
|
|
@ -224,6 +224,7 @@ public:
|
|||
virtual void DeviceLost() = 0;
|
||||
virtual void ReapplyGfxState() = 0;
|
||||
virtual void SyncThread() = 0;
|
||||
virtual u64 GetTickEstimate() = 0;
|
||||
virtual void DoState(PointerWrap &p) = 0;
|
||||
|
||||
// Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*.
|
||||
|
|
Loading…
Add table
Reference in a new issue