GPU: Defer frame done if not running events

Prevents interruption/execution exiting if the frame was ticked over
by a MMIO access, e.g. reading GPUSTAT.
This commit is contained in:
Stenzek 2024-09-22 12:35:17 +10:00
parent 88bc3a2278
commit f169b892c1
No known key found for this signature in database
3 changed files with 26 additions and 1 deletions

View File

@ -49,6 +49,9 @@ static TimingEvent s_crtc_tick_event(
static TimingEvent s_command_tick_event(
"GPU Command Tick", 1, 1, [](void* param, TickCount ticks, TickCount ticks_late) { g_gpu->CommandTickEvent(ticks); },
nullptr);
static TimingEvent s_frame_done_event(
"Frame Done", 1, 1, [](void* param, TickCount ticks, TickCount ticks_late) { g_gpu->FrameDoneEvent(ticks); },
nullptr);
static std::deque<std::thread> s_screenshot_threads;
static std::mutex s_screenshot_threads_mutex;
@ -76,6 +79,7 @@ GPU::~GPU()
{
s_command_tick_event.Deactivate();
s_crtc_tick_event.Deactivate();
s_frame_done_event.Deactivate();
JoinScreenshotThreads();
DestroyDeinterlaceTextures();
@ -1089,7 +1093,19 @@ void GPU::CRTCTickEvent(TickCount ticks)
UpdateCRTCTickEvent();
if (frame_done)
System::FrameDone();
{
// we can't issue frame done if we're in the middle of executing a rec block, e.g. from reading GPUSTAT
// defer it until the end of the block in this case.
if (!TimingEvents::IsRunningEvents()) [[unlikely]]
{
DEBUG_LOG("Deferring frame done call");
s_frame_done_event.Schedule(0);
}
else
{
System::FrameDone();
}
}
}
void GPU::CommandTickEvent(TickCount ticks)
@ -1102,6 +1118,13 @@ void GPU::CommandTickEvent(TickCount ticks)
m_executing_commands = false;
}
void GPU::FrameDoneEvent(TickCount ticks)
{
DebugAssert(TimingEvents::IsRunningEvents());
s_frame_done_event.Deactivate();
System::FrameDone();
}
void GPU::UpdateCommandTickEvent()
{
if (m_pending_command_ticks <= 0)

View File

@ -206,6 +206,7 @@ public:
// Ticks for hblank/vblank.
void CRTCTickEvent(TickCount ticks);
void CommandTickEvent(TickCount ticks);
void FrameDoneEvent(TickCount ticks);
// Dumps raw VRAM to a file.
bool DumpVRAMToFile(const char* filename);

View File

@ -1479,6 +1479,7 @@ void System::ResetSystem()
Host::AddIconOSDMessage("SystemReset", ICON_FA_POWER_OFF, TRANSLATE_STR("OSDMessage", "System reset."),
Host::OSD_QUICK_DURATION);
ResetPerformanceCounters();
InterruptExecution();
}