mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-03 03:05:18 +02:00
Legacy Win32 debugger: fix the painting problem with a frame-scoped mutex
Debugger windows (register list, disassembly view, memory view, breakpoint/ thread/module/stack lists, watch list) read CPU-thread-owned state directly from the GUI thread's WM_PAINT/list-fill handlers, racing against the CPU thread. Routing every read through Core_RunOnCPUThread would be too slow for something invoked continuously on paint/list-refresh. Add g_frameMutex (Core.h/Core.cpp), held by NativeFrame() only across the span where it actually touches that state (running the CPU, processing breakpoints, running the ImGui debugger) - not across input handling or the present/frame-pacing waits. Debugger windows now hold the same mutex while reading, giving synchronized reads without the round-trip cost of queuing to the CPU thread. CtrlRegisterList::onPaint() goes back to always reading live values (now safe under the lock) and grays them out by color alone while the core is running, rather than the earlier snapshot-caching approach. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hqm11k99viLfbJm2MkH4BH
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
03dcfd3931
commit
f72709feb0
+25
-17
@@ -1257,29 +1257,37 @@ void NativeFrame(GraphicsContext *graphicsContext) {
|
||||
|
||||
g_requestManager.ProcessRequests();
|
||||
|
||||
g_breakpoints.Frame();
|
||||
// Guards the span where we actually touch CPU-thread-owned debugger state (breakpoints,
|
||||
// symbol map, registers, memory, etc.) against unsynchronized reads from other threads' paint
|
||||
// handlers - see g_frameMutex in Core.h.
|
||||
ScreenRenderFlags renderFlags = ScreenRenderFlags::NONE;
|
||||
{
|
||||
std::lock_guard<std::mutex> emuStateGuard(g_frameMutex);
|
||||
|
||||
// Apply the UIContext bounds as a 2D transformation matrix.
|
||||
// NOTE: We compensate for the Y and Z conventions in the shaders, so we can use the same matrices in all backends.
|
||||
Matrix4x4 ortho = ComputeOrthoMatrix(g_display.dp_xres, g_display.dp_yres, g_draw->GetDeviceCaps().coordConvention);
|
||||
g_breakpoints.Frame();
|
||||
|
||||
// Can be overridden by sceDisplay which may pass true for the second argument.
|
||||
g_frameTiming.ComputePresentMode(g_draw, false);
|
||||
// Apply the UIContext bounds as a 2D transformation matrix.
|
||||
// NOTE: We compensate for the Y and Z conventions in the shaders, so we can use the same matrices in all backends.
|
||||
Matrix4x4 ortho = ComputeOrthoMatrix(g_display.dp_xres, g_display.dp_yres, g_draw->GetDeviceCaps().coordConvention);
|
||||
|
||||
ui_draw2d.PushDrawMatrix(ortho);
|
||||
// Can be overridden by sceDisplay which may pass true for the second argument.
|
||||
g_frameTiming.ComputePresentMode(g_draw, false);
|
||||
|
||||
g_screenManager->getUIContext()->SetTintSaturation(g_Config.fUITint, g_Config.fUISaturation);
|
||||
ui_draw2d.PushDrawMatrix(ortho);
|
||||
|
||||
// All actual rendering (and also emulation) happens in this render() call.
|
||||
ScreenRenderFlags renderFlags = g_screenManager->render();
|
||||
if (g_screenManager->getUIContext()->Text()) {
|
||||
g_screenManager->getUIContext()->Text()->OncePerFrame();
|
||||
g_screenManager->getUIContext()->SetTintSaturation(g_Config.fUITint, g_Config.fUISaturation);
|
||||
|
||||
// All actual rendering (and also emulation) happens in this render() call.
|
||||
renderFlags = g_screenManager->render();
|
||||
if (g_screenManager->getUIContext()->Text()) {
|
||||
g_screenManager->getUIContext()->Text()->OncePerFrame();
|
||||
}
|
||||
|
||||
ui_draw2d.PopDrawMatrix();
|
||||
|
||||
runImDebugger(g_draw);
|
||||
renderImDebugger(g_draw);
|
||||
}
|
||||
|
||||
ui_draw2d.PopDrawMatrix();
|
||||
|
||||
runImDebugger(g_draw);
|
||||
renderImDebugger(g_draw);
|
||||
g_draw->EndFrame();
|
||||
|
||||
// This, between EndFrame and Present, is where we should actually wait to do present time management.
|
||||
|
||||
Reference in New Issue
Block a user