mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
GS: record a complete dump under the pipelined back-thread split
The dump's transfer and ReadFIFO hooks sit on the parse path, and its initial state came from Freeze() on the renderer. Under GSBackThreadMode=Pipelined the parse path belongs to the front object, so both were reading the wrong object: the front's transfers never reached the dump at all. A Rogue Galaxy capture that should be 39.4 MB of packets came out with 90 KB -- 0.2% of the stream, the ReadFIFO and VSync packets alone -- and replayed as nothing. GSQueueSnapshot warned about it rather than fixing it (GV7-2). The dump stays owned by the renderer, which opens and closes it on the present path; the parse side reaches it through GetDumpSink(), which routes via m_mem_target, and the initial freeze goes through a new m_parse_target, the inverse pointer. Both paths run on the MTGS thread -- the front's runahead is over the back thread, not over the thread handling vsync -- so the front writes straight into the back's dump with no synchronisation. m_parse_target->Freeze() is the same call GSfreeze makes for a savestate, which already drains and already takes registers from the front and local memory from the back. Verified on a Rogue Galaxy savestate, frame-stepped over PINE so both arms start from the identical state: the mode 3 dump is byte-identical to the mode 0 dump, 4.2 MB of initial state and 39.4 MB of packets, and it replays in gsrunner to ten frames identical under both modes. Two mode 0 runs are likewise identical, so the harness has no slack. Reverting just the transfer sink reproduces the 90 KB dump, so the comparison has teeth. Two bytes of bookkeeping ride along: GSQueueSnapshot loses the warning, and the MsgGSDump reply loses pipelined_incomplete, which now has nothing to report. Whether the split engaged is a genuine question, so it moves to the stats reply as gs_front_parser, next to gs_back_thread_pct where it belongs.
This commit is contained in:
+8
-8
@@ -369,7 +369,7 @@ namespace PINEServer
|
||||
"\"tc_source_hit\":{:.1f},\"tc_source_miss\":{:.1f},"
|
||||
"\"tc_target_hit\":{:.1f},\"tc_target_miss\":{:.1f},"
|
||||
"\"hash_cache_hit\":{:.1f},\"hash_cache_miss\":{:.1f},"
|
||||
"\"gs_memory\":\"{}\",\"frame_number\":{},"
|
||||
"\"gs_memory\":\"{}\",\"frame_number\":{},\"gs_front_parser\":{},"
|
||||
"\"renderer\":\"{}\",\"device_name\":\"{}\",\"driver_info\":\"{}\""
|
||||
"}}",
|
||||
PerformanceMetrics::GetFPS(), PerformanceMetrics::GetInternalFPS(), PerformanceMetrics::GetSpeed(),
|
||||
@@ -391,7 +391,10 @@ namespace PINEServer
|
||||
counter(GSPerfMon::TCSourceHit), counter(GSPerfMon::TCSourceMiss),
|
||||
counter(GSPerfMon::TCTargetHit), counter(GSPerfMon::TCTargetMiss),
|
||||
counter(GSPerfMon::HashCacheHit), counter(GSPerfMon::HashCacheMiss),
|
||||
gs_memory.view(), PerformanceMetrics::GetFrameNumber(),
|
||||
// Whether the two-object split actually engaged, which the BackThreadMode setting
|
||||
// alone does not tell you -- it downgrades to lockstep on an unsupported config.
|
||||
// True is also what makes gs_back_thread_* worth reading next to gs_thread_*.
|
||||
gs_memory.view(), PerformanceMetrics::GetFrameNumber(), GSHasFrontParser() ? "true" : "false",
|
||||
Pcsx2Config::GSOptions::GetRendererName(EmuConfig.GS.Renderer), device_name, driver_info);
|
||||
}
|
||||
|
||||
@@ -464,7 +467,7 @@ namespace PINEServer
|
||||
}
|
||||
}
|
||||
|
||||
bool queued = false, stopped = false, incomplete = false;
|
||||
bool queued = false, stopped = false;
|
||||
std::string base;
|
||||
const char* dump_ext = "";
|
||||
const char* reason = "";
|
||||
@@ -509,18 +512,15 @@ namespace PINEServer
|
||||
dump_ext = ".gs.zst";
|
||||
break;
|
||||
}
|
||||
|
||||
incomplete = GSHasFrontParser();
|
||||
});
|
||||
MTGS::WaitGS(false);
|
||||
},
|
||||
true);
|
||||
|
||||
*reply = fmt::format(
|
||||
"{{\"queued\":{},\"stopped\":{},\"frames\":{},\"path\":\"{}\","
|
||||
"\"pipelined_incomplete\":{},\"reason\":\"{}\"}}",
|
||||
"{{\"queued\":{},\"stopped\":{},\"frames\":{},\"path\":\"{}\",\"reason\":\"{}\"}}",
|
||||
queued ? "true" : "false", stopped ? "true" : "false", frames,
|
||||
queued ? JsonEscape(base + dump_ext) : std::string(), incomplete ? "true" : "false", reason);
|
||||
queued ? JsonEscape(base + dump_ext) : std::string(), reason);
|
||||
return true;
|
||||
}
|
||||
} // namespace PINEServer
|
||||
|
||||
Reference in New Issue
Block a user