From af2ecc3c03a7f4b150f5ecc0f233993644141d16 Mon Sep 17 00:00:00 2001 From: chrg6 Date: Fri, 13 Nov 2026 19:55:46 -0500 Subject: [PATCH] Correct the comments on RivaTuner Statistics Server's pacing beside the ceiling, the state file's writers and the crash path. The review found three comments that claimed more than the code does. rtss_decide.h rtss_pace_period and frame_rate.c (above frame_step_cap_ns) said the frames RTSS lets through always come further apart than the 240 ceiling, so the two limiters never stack: at a limit of 240, or unlimited, which RTSS gets as 240, the ceiling is RTSS's own period, and both may hold a frame. rtss_limit.c state_put said it runs on the worker thread only, but rtss_limit_restore's put back calls it on the exiting thread, under the lock. And rtss_limit.c's header said a crash and a fatal error make no call into RTSS's library, which holds only while the state file has the run's line. The comments now say so, and the header names the exception at 240. (The comment above rtss_decide was rewrapped and lost its reference to rtss_fresh with the unproven-hold rule.) No behaviour changes. Checks that passed: tests/rtss_limit_check.py, tests/frame_step_check.py, pass_cc_check.py --wall on rtss_limit.c and frame_rate.c (only frame_rate.c's existing game_interval warning), tools/check_content.py --staged. Co-Authored-By: Claude Opus 5.5 --- runtime/frame_rate.c | 5 +++-- runtime/rtss_decide.h | 3 ++- runtime/rtss_limit.c | 12 +++++++----- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/runtime/frame_rate.c b/runtime/frame_rate.c index be59e9cb..87e74553 100644 --- a/runtime/frame_rate.c +++ b/runtime/frame_rate.c @@ -275,8 +275,9 @@ double frame_step_game_hz(void) { } // RivaTuner Statistics Server (rtss_limit.c) gets the same limit; while it limits this process the pacer holds the -// frames only to LIMIT_FREE_MAX_HZ, the ceiling the game's code needs, so the two never stack, and it takes the limit -// back once no picture went out for 200 ms (rtss_decide.h rtss_pace_period): a minimised window or a frame hold leaves +// frames only to LIMIT_FREE_MAX_HZ, the ceiling the game's code needs, so the two do not stack, except at a limit of +// 240 or unlimited, where the ceiling is RTSS's own period; and it takes the limit back once no picture went out for +// 200 ms (rtss_decide.h rtss_pace_period): a minimised window or a frame hold leaves // RTSS no present to hold. While a movie plays the pacer holds the movie's rate and keeps its slots whatever RTSS does. // NX2NAVI_RTSS=0 and frame generation (RTSS would count the generated frames) keep it out, and so does a driver's low // latency while it is in effect (vk_lowlat.c): the driver holds the limit where the frame starts, and RTSS would hold diff --git a/runtime/rtss_decide.h b/runtime/rtss_decide.h index b1e10789..6dcc0b36 100644 --- a/runtime/rtss_decide.h +++ b/runtime/rtss_decide.h @@ -330,7 +330,8 @@ static inline void rtss_why_text(char *out, size_t n, const RtssOut *o, int fail // gives RTSS nothing to hold, and a pacer that held nothing then let the quick menu run at the 640-700 fps that read // address 0 (frame_rate.c LIMIT_FREE_MAX_HZ). While RTSS holds, the ceiling's period and never 0: the frames RTSS lets // through come further apart than that, so pace() waits for none of them, and it still holds the game's frames to the -// ceiling the game's code needs. +// ceiling the game's code needs. The exception is a limit of 240, or unlimited, which RTSS gets as 240: there the +// ceiling is RTSS's own period, and both may hold a frame. static inline uint64_t rtss_pace_period(int holds, int movie, uint64_t now_ns, uint64_t hosted_ns, uint64_t period, uint64_t ceiling) { uint64_t idle = now_ns > hosted_ns ? now_ns - hosted_ns : 0; diff --git a/runtime/rtss_limit.c b/runtime/rtss_limit.c index 09ee7420..f3877199 100644 --- a/runtime/rtss_limit.c +++ b/runtime/rtss_limit.c @@ -1,7 +1,8 @@ // RivaTuner Statistics Server as the frame limiter (frame_rate.c frame_step_cap_ns): where RTSS is installed and running, // the frame limit goes into RTSS's profile for this executable and, while RTSS is seen holding the game to it, the -// game's own pacer keeps only the 240-frame ceiling (rtss_decide.h rtss_pace_period), so there is one limiter. -// Anywhere else, or when any step fails, the game's own limiter works as it always did. +// game's own pacer keeps only the 240-frame ceiling (rtss_decide.h rtss_pace_period), so there is one limiter (at a +// limit of 240 the ceiling is RTSS's own period). Anywhere else, or when any step fails, the game's own limiter works +// as it always did. // // RTSS's hooks library (RTSSHooks64.dll in the folder its installer records under // HKLM\SOFTWARE\WOW6432Node\Unwinder\RTSS, InstallDir) exports the profile calls, loaded here at run time: @@ -32,7 +33,8 @@ // profile is back: an exit that skips the restore (a kill, a hang, the device-lost watchdog) leaves the line, and the // next start puts the profile back from it before it changes anything (left_start, restore_left), unless the player // changed the profile since; a start with NX2NAVI_RTSS=0 only logs it. A crash and a fatal error leave it to that start -// too (rtss_limit_crash), with no call into RTSS's library from the failing process. +// too (rtss_limit_crash), with no call into RTSS's library from the failing process, unless the file could not be +// written: then they put the profile back as an orderly exit does, but not from the worker's own thread. // // NX2NAVI_RTSS=0 keeps RTSS out of it. Frame generation keeps it out too (RTSS counts every presented frame, the // generated ones included), and so does a driver's low latency (vk_lowlat.c), which holds the frames where they start. @@ -167,8 +169,8 @@ static int write_limit(DWORD limit, DWORD denominator) { return l == limit && (!has_denominator || d == denominator) ? 1 : -1; } -// The state file with this profile's line set to r, or removed for r NULL; the file goes once it holds no line. Worker -// thread only, under lock. 1 when the file holds what was asked. +// The state file with this profile's line set to r, or removed for r NULL; the file goes once it holds no line. Under +// lock: the worker, or rtss_limit_restore's thread at the exit. 1 when the file holds what was asked. static int state_put(const RtssSaved *r) { if (state_off || !*state_path) return 0; uint64_t n = 0;