Core: Skip duplicate frames when using frame advance

It used to be the case that frame advance skipped duplicate frames
(i.e. it would take 30 frame advances to get through one second
of emulated time in a 30 fps game), but this broke in 9c5c3c0.
Skipping duplicate frames making TASing less annoying.
This commit is contained in:
JosJuice
2020-04-07 19:37:32 +02:00
parent 1a42355f96
commit 812ad4257c
4 changed files with 54 additions and 28 deletions

View File

@ -77,6 +77,7 @@
#include "InputCommon/ControllerInterface/ControllerInterface.h"
#include "InputCommon/GCAdapter.h"
#include "VideoCommon/AsyncRequests.h"
#include "VideoCommon/Fifo.h"
#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/RenderBase.h"
@ -104,6 +105,7 @@ static std::thread s_cpu_thread;
static bool s_request_refresh_info = false;
static bool s_is_throttler_temp_disabled = false;
static bool s_frame_step = false;
static std::atomic<bool> s_stop_frame_step;
#ifdef USE_MEMORYWATCHER
static std::unique_ptr<MemoryWatcher> s_memory_watcher;
@ -863,18 +865,28 @@ void VideoThrottle()
void Callback_FramePresented()
{
s_drawn_frame++;
s_stop_frame_step.store(true);
}
// Called from VideoInterface::Update (CPU thread) at emulated field boundaries
void Callback_NewField()
{
Movie::FrameUpdate();
if (s_frame_step)
{
s_frame_step = false;
CPU::Break();
if (s_on_state_changed_callback)
s_on_state_changed_callback(Core::GetState());
// To ensure that s_stop_frame_step is up to date, wait for the GPU thread queue to empty,
// since it is may contain a swap event (which will call Callback_FramePresented). This hurts
// the performance a little, but luckily, performance matters less when using frame stepping.
AsyncRequests::GetInstance()->WaitForEmptyQueue();
// Only stop the frame stepping if a new frame was displayed
// (as opposed to the previous frame being displayed for another frame).
if (s_stop_frame_step.load())
{
s_frame_step = false;
CPU::Break();
if (s_on_state_changed_callback)
s_on_state_changed_callback(Core::GetState());
}
}
}
@ -1045,6 +1057,7 @@ void DoFrameStep()
if (GetState() == State::Paused)
{
// if already paused, frame advance for 1 frame
s_stop_frame_step = false;
s_frame_step = true;
RequestRefreshInfo();
SetState(State::Running);