Log RivaTuner Statistics Server's hold only while its want is still the current one.

The review found that A-11's fix stores the hold after every decision but also logs it then: when the want changed
while the worker wrote the profile (frame generation switched on during the first write), rtss_limit.c set_active
logged "RivaTuner Statistics Server does the limiting; the game's own limiter stands aside" while the game's limiter
was pacing the new want (rtss_limit_active compares the hold with the want), and the kept-out line followed one poll
later. set_active still stores the hold every time, so that a want going w, w2 and w again never finds an older hold,
but logs a hold only while the want is still the one decided for; a decision that RTSS does not hold the game is
logged as before. The next poll logs what holds the newer want.

tests/rtss_worker_check.c active_logged switches frame generation on inside the first SaveProfile (a hook in the fake
RTSS): no line may say RTSS does the limiting, the next poll logs the kept-out line, and a later limit is held and
logged. It fails on the code before this change. Log only; rtss_limit_check passes 27 of 27, active_race included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
chrg6
2026-11-13 17:52:08 -05:00
parent 4c919882fa
commit 55e03cf792
2 changed files with 33 additions and 2 deletions

View File

@@ -222,11 +222,13 @@ static void put_back_op(void *ctx, const RtssOut *o) { // rtss_poll's RtssOps.
// Whether RTSS holds the game to the want w this poll read, and the log of which limiter is in use: the first decision,
// then each change. The want may have changed since the poll read it: rtss_limit_active compares the two, so a stale
// store never lets the game's limiter stand aside for a newer want.
// store never lets the game's limiter stand aside for a newer want. The store is made either way (a want that went
// w, w2, w again must not find an older hold), but a hold is logged only while its want is still the current one: the
// game's limiter paces a newer want, and the next poll logs what holds it.
static void set_active(int64_t w, int on, const char *why) {
static int logged = -1;
atomic_store(&active_for, on ? w : RTSS_UNSET);
if (logged == on) return;
if (logged == on || (on && atomic_load(&want) != w)) return;
logged = on;
if (on) rt_log("frame rate: RivaTuner Statistics Server does the limiting; the game's own limiter stands aside");
else rt_log("frame rate: the game's own limiter (%s)", why);

View File

@@ -67,9 +67,15 @@ static void WINAPI f_load(LPCSTR name) {
(void)name;
loaded = own.exists ? own : global;
}
static void (*during_save)(void); // runs inside the next SaveProfile, once
static void WINAPI f_save(LPCSTR name) {
(void)name;
saves++;
if (during_save) {
void (*f)(void) = during_save;
during_save = NULL;
f();
}
if (readonly) return;
DWORD stamp = own.stamp;
own = loaded, own.exists = 1, own.stamp = stamp;
@@ -453,6 +459,28 @@ static void active_race(void) {
CHECK(!hits, "the game's limiter stood aside for a kept-out want %ld times", hits);
}
// Frame generation switched on while the worker writes the first limit: RTSS holds that limit, but the game's limiter
// paces the kept-out want, so the log must not say RTSS does the limiting; the next poll logs the kept-out line. A later
// limit is held and logged as usual.
static void framegen_on(void) { rtss_limit_want(RTSS_OUT_FRAMEGEN); }
static void active_logged(void) {
app_set(1, 0xA, 1000, 2000, 60);
during_save = framegen_on;
ask(60000);
show("frame generation switched on during the first write");
CHECK(own.exists && own.limit == 60, "the limit went into the profile");
CHECK(!rtss_limit_active(), "the game's limiter paces the kept-out want");
CHECK(!logged("does the limiting"), "no line says RTSS does the limiting");
poll();
show("the next poll");
CHECK(logged("the game's own limiter (RivaTuner Statistics Server kept out: frame generation)"), "the kept-out line");
CHECK(!logged("does the limiting"), "still no line says RTSS does the limiting");
ask(60000);
poll();
show("frame generation off");
CHECK(rtss_limit_active() && logged("does the limiting; the game's own limiter stands aside"), "held and logged");
}
// A limit of a fractional monitor (display at 59.94 and 143.856 Hz): an RTSS that knows the denominator holds it as it
// is, one that does not holds it rounded to whole frames, and the log says what the profile holds, not what was asked.
static void round_logged(void) {
@@ -721,6 +749,7 @@ static const struct { const char *name; void (*run)(void); } scenarios[] = {
{"kept_lowlat_then_limit", kept_lowlat_then_limit},
{"kept_framegen", kept_framegen},
{"active_race", active_race},
{"active_logged", active_logged},
{"round_logged", round_logged},
{"round_logged_whole", round_logged_whole},
{"start_off_present", start_off_present},