Commit Graph
41 Commits
Author SHA1 Message Date
Brian Degenhardt 7f93a80dd7 PerformanceMetrics: count the GS back thread
Under GSBackThreadMode >= Lockstep roughly half the GS work moves to a second
thread, and every surface that reports GS cost -- OSD, PerfLog, the Qt status
bar, PINE stats, gsrunner's @HWSTAT@ block -- measured the MTGS thread alone.
So the split read as a large GS saving. It is not: on a Rogue Galaxy savestate
here, mode 0 costs 15.8% / 2.63 ms and mode 3 costs 17.0% / 2.84 ms plus
14.2% / 2.37 ms on the back thread -- about twice the total GS CPU time, bought
to halve the critical path. That is a real trade, but nobody could see it.

The back thread registers its own handle at entry, as the SW rasterizer workers
do; StopBackThread clears it after the join. Unlike every other handle here it
is written by a thread other than the one sampling it, so the handle and its
running total sit behind a mutex taken twice a second. Installing a handle
rebases the total off it, so the first window after a GSreopen respawn measures
the new thread rather than its difference against the retired one's.

The figure is omitted, not reported as zero, wherever a back thread does not
exist -- otherwise a mode 0 vs mode 3 comparison reads a permanent 0% as
meaningful. gsrunner latches the presence flag during the run because DumpStats
executes after VMManager::Shutdown, by which point the thread has joined.
2026-07-30 21:55:58 -07:00
Brian Degenhardt 975e408ed5 PINE: add a GS-dump opcode so a script can capture without a hotkey
MsgGSDump (0x14, ARMSX2-local) queues a GS dump of the next N frames:
[u32 frames][u32 path_len][path bytes], where frames == 0 stops a recording
dump and UINT32_MAX records until stopped -- the same press/release pair the
GSDumpMultiFrame hotkey binds. The reply is JSON carrying the resolved dump
path, so a client knows the file to wait for instead of guessing at the
snapshots folder's auto-naming.

Three things the naive version of this gets wrong, all found by testing it
against a live Dragon Quest VIII:

QueueSnapshot honours a caller-supplied path only when it ends in .png, and
silently substitutes an auto-named file otherwise -- a scripted client would
write somewhere it never looks. Normalise the path up front instead, dropping
a .gs/.gs.xz/.gs.zst/.png suffix if the caller spelled one out so that naming
the file you want does not earn a doubled extension.

A request that arrives while a dump is already recording creates no second
dump: the VSync handler only opens one when none exists. It writes a stray
screenshot, and worse, overwrites the running dump's remaining frame count and
cuts it short. The first version of this replied with a path for a file that
was never created and truncated the recording that was. Refuse instead, with
reason "already recording"; the caller can stop the running dump first. The
same defect reachable via the Screenshot hotkey is left alone here -- it is a
renderer behaviour change and belongs in its own commit.

The PINE thread cannot push MTGS packets: the ring is single-producer and that
producer is the EE thread. Take the same two-hop route BuildStatsJson already
documents -- Host::RunOnCPUThread, then RunOnGSThread -- and read GSConfig's
compression method on the GS thread, since it decides the extension.

QueueSnapshot and GSQueueSnapshot now return whether they took the request;
existing callers ignore it. GSIsDumpRecording and GSHasFrontParser expose the
two pieces of GS-thread state the reply needs. pipelined_incomplete surfaces
the known GV7-2 gap rather than letting a script collect corrupt dumps.

Verified live: every promised path was written, refusals produced no files,
and all three dump shapes replay in gsrunner -- single-frame as 4 (2) frames,
a stopped multi-frame recording as 186 (91).
2026-07-30 21:55:58 -07:00
Brian Degenhardt 2e9762d1d6 Rebrand user-facing PCSX2 references to ARMSX2; fix Help menu
Help menu (Linux desktop and everywhere):
- GitHub Repository pointed at a dead branch (/tree/macOS); now the repo root.
- Removed the PCSX2 Wiki and Documentation items (they linked pcsx2.net /
  wiki.pcsx2.net, impersonating upstream) and replaced them with a single
  ARMSX2 Website item pointing at armsx2.net.
- Removed Check for Updates (the auto-updater is disabled, so it only ever
  errored) and About Qt.
- About dialog body reworded to describe ARMSX2 (crediting PCSX2 as upstream).

Wrong-destination / impersonation fixes:
- PINE MsgVersion reply now identifies as "ARMSX2" (buffer sized accordingly).
- Bug-report links (GS unknown-video-mode / invalid-lod, EE COP2 warnings) now
  point at github.com/ARMSX2/ARMSX2/issues.
- "download a fresh copy" recovery messages (VMManager, SaveState, Windows
  updater, Win32 update-not-supported dialog) now point at armsx2.net.
- Auto-updater release/compare endpoints and staging-dir name de-PCSX2'd.

UI strings: setup wizard, cover downloader, and the Settings widgets (Qt) plus
their Big-Picture/Fullscreen ImGui twins now say ARMSX2. The "PCSX2Blue" theme
settings key is left unchanged (persisted / matched in code); only its display
name changes.

Interop identifiers deliberately left as-is: the PINE socket name (pcsx2.sock,
for PINE-client compatibility) and the RetroAchievements client name.
2026-07-23 19:48:13 -07:00
Brian Degenhardt d2bce662d4 PINE: marshal GS-stats sampling onto the CPU thread to avoid MTGS deadlock
The PINE server thread called MTGS::RunOnGSThread + WaitGS directly to sample
GS memory stats and device/driver info. The MTGS ring is single-producer:
m_WritePos is owned by the EE/CPU thread, so pushing a packet from the PINE
thread creates a second producer that races the EE thread's own ring writes,
desyncing the pending-packet count. That lost wakeup deadlocks the EE thread
(parked in WaitGS) against the GS thread (asleep in WaitForWork).

Marshal the sample onto the CPU thread first -- the legitimate ring producer --
and block until the GS-owned data has been gathered.
2026-07-23 19:46:52 -07:00
Brian Degenhardt 9a4bd0f56f GS tooling: report GPU device and driver identity in stats output
Both `gsctl stats` and `gsrunner -stats-json` reported counters with no
indication of which GPU or driver produced them, so a stats blob from a
tester was not attributable — and driver identity is the axis nearly every
mobile GPU behaviour turns on.

This matters beyond provenance. Several GS features are force-overridden
per-driver (framebuffer fetch and texture barriers are forced on for Adreno
regardless of INI), so without knowing the driver you cannot tell whether a
settings A/B was applied at all or silently compared a config against itself.

gsrunner captures the strings on the GS thread at first present rather than
at shutdown, where the device may already be gone. Both emitters escape the
values, since GetDriverInfo() is multi-line on Vulkan.
2026-07-22 21:16:45 -07:00
Brian Degenhardt 4fc1fa7c5f PINE: add statistics and settings opcodes, plus a gsctl client
Debugging a GS performance problem meant restarting the emulator and reloading a
savestate for every "did you try setting X?", and the only way to read the
statistics that drive that decision was to look at the OSD. PINE already
provides a unix socket, a thread, framing, a config key and the RunOnCPUThread
marshalling pattern, but its opcodes stop at guest-RAM peek/poke plus savestates
and game identity -- no host statistics, no settings.

Adds four ARMSX2-local opcodes at 0x10+ (upstream PINE ends at 0xF, so a generic
client will never send them):

  MsgGetStats     PerformanceMetrics, all GSPerfMon counters and the texture
                  cache memory figures, as JSON.
  MsgGetSetting   read a setting by section/key.
  MsgSetSetting   write a setting, apply it, and report whether the key forces a
                  GS device reopen.
  MsgFrameAdvance step a paused VM.

MsgSetSetting writes the persisted key rather than poking EmuConfig directly,
because a direct poke is silently reverted by the next ApplySettings, which
re-derives EmuConfig from the INI layer stack. The restart_required answer comes
from a new GSOptions::IsRestartOption, sitting next to RestartOptionsAreEqual so
the two lists stay in sync.

Statistics are gathered on the PINE thread. PerformanceMetrics and g_perfmon are
benign scalar reads, but GSgetMemoryStats dereferences g_texture_cache and
g_gs_device, which are GS-thread owned, so that one is marshalled through
RunOnGSThread.

tools/gsctl.py is a stdlib-only client emitting JSON on stdout.

Verified against a headless gsrunner replay: toggling accurate_blending_unit
between 0 and 5 over the socket moves barriers 1.0 <-> 91.5 and draw calls
55.5 <-> 101.5, repeatably, with no restart.
2026-07-22 21:16:45 -07:00
chaoticgd b67e793283 PINE: Disallow access to pages with custom VTLB handlers 2026-06-28 16:46:13 -04:00
chaoticgd 3df128d9f9 PINE: Ignore SIGPIPE properly on macOS 2026-06-06 09:59:21 -04:00
chaoticgd b3834427bc PINE: Don't test for a valid VM when checking emulator version 2026-06-01 23:55:19 +02:00
SternXD d983b2b066 Copyright: Change year from 2002-2025 to 2002-2026 2026-01-15 00:22:32 +01:00
chaoticgd e8c2cfa843 SaveState: Rework error handling when saving states 2025-12-13 21:42:52 -05:00
chaoticgd 764875ddbf Qt: Add setting to show state load errors using a dialog or OSD message 2025-12-13 21:42:52 -05:00
chaoticgd 8d30e8cee8 FullscreenUI: Fix save state loading 2025-11-28 10:50:41 -05:00
chaoticgd bf10b55aa1 PINE: Use the correct naming convention for static globals 2025-09-13 14:45:10 -04:00
chaoticgd 43d9ea99b0 PINE: Don't crash with SIGPIPE if the client dies while writing 2025-09-13 14:45:10 -04:00
chaoticgd 62fa768e60 PINE: Give the server thread a name 2025-07-09 04:19:09 +02:00
TheTechnician27 23fd57f641 Copyright: Change year from 2002-2024 to 2002-2025 2025-01-20 05:07:26 +01:00
chaoticgd f69d5835b8 PINE: Fix stack buffer overflow for long XDG_RUNTIME_DIR paths 2024-11-22 14:10:32 -05:00
chaoticgd eeb919325e Misc: Minimise the amount of work done when svnrev.h is updated 2024-11-12 09:14:39 -05:00
GovanifY 132431b7c8 headers: relicense to GPL-3.0+
also update to 2024 while i'm at it
2024-07-30 17:17:13 -04:00
GovanifY 325e219bb1 PINE: fix save state regression introduced during the switch to Qt
Ensure thread safety when loading/saving state
2024-01-25 20:05:44 +10:00
Stenzek ff34150b15 Build: Simplify Git version extraction
Get rid of SysForwardDefs.h
Use last known git tag to determine version info, if it is not a tagged commit.
2024-01-15 15:35:21 +10:00
Stenzek 51ceab1f3c PINE: Convert from class to namespace
Fewer global objects, indirect includes via headers.
2024-01-12 12:57:28 +10:00
Stenzek 2257992a3f PINE: Tidy up and fix shutdown hang on Linux 2024-01-12 12:57:28 +10:00
GovanifY 72787d103f PINE: fix regressions introduced in #10448 2024-01-08 22:01:24 +00:00