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;