Replies: 3 comments 11 replies
|
I think I could take this framerate cap for the weekend/monday testing on my GPU along with this one: #61. Will verify accross my Steam lib on 5080, thanks. BTW what GPU do you have for testing? I'm particularly looking for somebody with 5090 for extensive testing, but with current pricing - well can't afford that... |
0 replies
|
I test on an RTX 5070 Ti at UWQHD (3440×1440), with the FPS target set to 100 across all my testing. That combination is what made the frame-cap behaviour easy to hit and reproduce — plenty of game menus and cinematics sit at a hard 60 or 30, well below that target, so the mismatch shows up constantly rather than as a one-off. |
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment

Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
First batch of planned PRs — overview before I open them
Four branches are ready or nearly ready. They touch completely disjoint file
sets, so they can be reviewed and merged in any order, independently — I
checked, there is not a single shared file between them.
Sizes below are against current
main(553c8ab). All four branches arealready rebased on it; none is stale.
agent/latency-without-overlayagent/boot-apply-single-sourceagent/externally-capped-framesburnerdadaptiveHappy to split, reorder, or drop any of these.
1.
agent/latency-without-overlay— document keeping latency markers with the overlay offProblem. In-game latency defaults to the overlay's state, so
--pb-overlay=0switches off NVAPI marker capture along with the HUD. That is a reasonable
default, but it silently removes the pacing signal that adaptive tier switching
reads, and nothing told the user how to get it back.
Change. Documents the explicit opt-in in the latency guide and the shim
reference. Also spells out that the leading
envis required: Lutris execs thecommand prefix directly rather than through a shell, so a bare
PB_INGAME_LATENCY=1would be taken as the program to run.Risk: none — documentation plus the tests that keep the docs honest.
Suggested first. It is the smallest, and it documents behaviour that 3
depends on users being able to enable.
2.
agent/boot-apply-single-source— read the boot checkbox from the daemonProblem. "Apply on startup" mixed two sources of truth. The daemon's per-GPU
boot set is the only thing that decides what applies at startup, but the
[ui] persist_on_startuppreference was read back to answer "what will bootdo". Nothing rewrites that key when the entry goes away, so it could only go
stale — a config holding
trueagainst an empty boot set showed "applies atstartup" for a boot with nothing to apply.
The per-GPU session cache had the same problem in the other direction, and that
is the damaging one: seeded once from the daemon, then authoritative for the
rest of the session, even though the daemon is re-read on every sync. Every
apply sends
--bootor--clear-bootfrom that state. Reachable withouttouching the GUI's boot controls at all:
penguin-burner-cli --restore-stock, which writes a boot entry throughits own
persist_on_startuppath;--clear-bootsilently wipes what step 2 wrote.Change. The no-UUID branch asks the daemon, which already answers for its
selected GPU. The cache now carries only intent the daemon has not been told
about yet — a freshly ticked box — dropped the moment the daemon reports it.
Reading the two with OR keeps one invariant: the box is never shown off while
the daemon holds an entry, so
--clear-bootonly goes out when there isgenuinely nothing to clear. The preference key keeps being written, and is
documented as what it is — a record of the user's choice, not a statement
about boot.
Also closes a test-isolation gap found on the way: the
winfixture patchedthe window module's autostart reader but not the mixin's own binding, so
building the window in tests reached the real daemon socket and the checkbox
started ticked or not depending on what that machine had saved.
Risk: low, contained to the GUI profile path. Each new test was confirmed to
fail against the previous behaviour, not merely to pass now.
3.
agent/externally-capped-frames— stop adaptive fighting an external frame capFour commits, and the largest behavioural change of the set. Mostly
burnerd/src/profile/adaptive.rs, with the matching runtime spec fields anduser docs.
Problem. With a target above an external frame cap — a menu locked at 60
while aiming for 100 — every branch of the slow ladder read the miss as "short
of clock". At that target 16.67 ms is well past
badly_slow, so the tier jumpedstraight to the top and sat there for the whole menu, burning power for frames
the cap would never let through.
What the four commits do
Judge whether the GPU is actually the limiter first. When it is loafing
and the CPU is not saturated either, nothing about the frame rate is a clock
problem, so the tier eases down instead of climbing. Easing reuses the
existing comfort-demotion path rather than introducing a second set of
timings. A saturated CPU is deliberately left to the existing cpu-bound
guard, keeping the two rules disjoint.
Latch the recognition against pacing, not utilisation. The first cut
oscillated on hardware — performance → balanced → efficiency, then straight
back — because utilisation was both the entry signal and the thing keeping it
alive, and utilisation is not independent of the tier: each step down makes
the card work harder for the same capped rate, climbing back over the entry
threshold and cancelling the recognition that caused the step. A cap holds
the frame rate steady whichever tier runs, so frametime is the one signal the
policy's own decisions cannot invalidate. Two ways out, both meaning "the
tier is the limit again": pacing degrades past the reference by more than
15%, or the card is flat out at 90%+.
Re-test the cap on the tick its latch is released. Observed live: a latch
dropped because pacing regressed past it, and the same tick promoted to the
top tier — with the card at 58% and the CPU at 10%, where nothing was short
of clock. "This reference stopped explaining the pacing" is a different claim
from "the tier is the limit now", and only the second justifies climbing. The
asymmetry is what makes it matter: a promotion takes one window, every step
back down pays its dwell.
Ease the tier down when nothing is being played, and make all three
utilisation bars configurable. Adaptive paces on frames, so with nothing
presenting it held whichever tier the last game left behind — a tuned card
sat on Performance for as long as the desktop stayed idle. An idle desktop
and a game we cannot measure look identical from the policy's seat;
utilisation separates them, and the margin is not close (idle desktop with a
compositor and a browser reads 3–4%, a game runs 50–90% even under an
external cap; the default bar sits at 20%). Entry is slow, exit immediate,
and with no utilisation reading at all the tier is held rather than lowered —
absence of a measurement is not evidence of an idle machine.
Compatibility. Both new spec fields are serde-defaulted, so a client
predating them still resolves against a strict
deny_unknown_fieldsspec. Thedaemon enforces the ordering of the three bars rather than clamping quietly.
Verification.
cargo test,cargo fmt --check,cargo clippyclean; fullpytest suite green. The oscillation test replays the measured utilisation climb
(30% → 85%) and asserts the tier only ever moves down; it was reproduced from
the live log before the fix.
This is the one I would most like your @jpietek opinion on before it becomes a PR,
since it changes tier-switching policy rather than fixing a bug in it.
All reactions