FUG-82: autoscale effect framerate (5-fps ladder + abort + app override) - #55
Open
issuefleet[bot] wants to merge 1 commit into
Open
FUG-82: autoscale effect framerate (5-fps ladder + abort + app override)#55issuefleet[bot] wants to merge 1 commit into
issuefleet[bot] wants to merge 1 commit into
Conversation
FUG-82 Autoscale framerate
Scale framerate to achieve consistent FPS in 5 FPS steps between 80 and 25 FPS. If 25 FPS is not achievable, abort the current effect (to prevent starving the other threads). There should be at least 5% headroom at any given FPS setting, and if more than x/N frames in a given interval are missed, the FPS target should be dropped. Also allow overriding the FPS target from the app; if the user-set FPS target is not achievable, abort the effect (and notify the user). |
issuefleet
Bot
force-pushed
the
agent/fug-82-autoscale-framerate
branch
from
August 9, 2026 02:30
edd70e8 to
dca7273
Compare
issuefleet
Bot
force-pushed
the
agent/fug-82-autoscale-framerate
branch
from
August 9, 2026 02:48
dca7273 to
99345e0
Compare
|
issuefleet
Bot
force-pushed
the
agent/fug-82-autoscale-framerate
branch
from
August 14, 2026 22:22
99345e0 to
931ca7f
Compare
… override
Effects rendered at a fixed ~30 fps regardless of how expensive the shader was,
so a heavy effect starved the WiFi/BLE tasks and stuttered while a cheap one
wasted headroom. Close the loop: adapt each effect's target FPS to its measured
per-frame cost on this device.
- New no_std crate //firmware/fps: a pure `FpsController` (thoroughly
host-unit-tested, integer-only) — a 25..80 fps ladder in 5-fps steps, a "5%
headroom" miss rule, an x/N missed-frame window that drops a rung (or steps up
when a clean window's worst frame still fits the next rung), a user-pin
override, and an abort decision when even the floor / pinned rate can't hold.
- Render loop (main.cpp/ffi.rs): measure every effect frame's cost (update +
shade + show; ungated from the perf tier), feed the controller, and sleep
period-minus-work so the frame INTERVAL tracks the target (a *consistent*
FPS). On an unachievable target the effect is parked (freeing the CPU) and the
network loop pushes an fps_state{aborted} to notify the app. The perf-ring
overrun budget now tracks the live target (cpu_hz / current_fps).
- Protocol: SetFps{target_fps} (0 = auto) + FpsState{target,current,min,max,
auto,aborted}; PerfReport gains current_fps.
- Web: client.setFps/onFpsState, a Framerate control (Auto / 25..80) in the perf
panel with a live readout, and an abort toast.
- Docs: perf-monitoring.md gains a "Framerate autoscaling" section.
Tests: firmware/fps unit tests (ladder/headroom/window/abort/pin/consistent
delay); host FFI test exercises set_fps -> fps_state + the pinned-abort path;
web proto round-trip for the new arms. esp32c6 firmware + all web/rust/python
protocol tests green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
issuefleet
Bot
force-pushed
the
agent/fug-82-autoscale-framerate
branch
from
August 15, 2026 21:34
931ca7f to
900912c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
FUG-82: Autoscale framerate
Effects rendered at a fixed ~30 fps regardless of shader cost, so a heavy effect starved the WiFi/BLE tasks and stuttered while a cheap one wasted headroom. This closes the loop: the render loop adapts each effect's target FPS to its real per-frame cost on the device, and aborts an effect it genuinely can't run.
Behavior (matches the issue)
set_fps{target_fps}pins an exact rate (snapped to the ladder);0returns to autoscale. A pinned rate the device can't hit aborts + notifies rather than silently dropping.period − work, so frame starts land one period apart.What's here
//firmware/fps— a pure,no_std, integer-onlyFpsControllerwith the ladder/headroom/window/abort/pin logic and 12 host unit tests.main.cpp/ffi.rs) — measures every effect frame's cost (ungated from the perf tier), drives the controller, parks-on-abort, pushesfps_state{aborted}from the network loop. Overrun budget now tracks the live target (cpu_hz / current_fps).SetFps(client arm 32) +FpsState(server arm 19);PerfReport.current_fps.client.setFps/onFpsState, a Framerate control (Auto / 25–80) with a live readout in the perf panel, and an abort toast.docs/design/perf-monitoring.md.Testing (green locally on the rebased tree)
//firmware/fps,//firmware/player_app:ffi_test(set_fps → fps_state, snap-to-rung, pinned-abort over the C ABI), the exhaustive-armphone_client_frames_test/session_test, plus fx_vm/arena/pulse/store;esp32c6builds-c opt.web_ts_typecheck_test;proto_testround-trips the new arms.Rebase notes
Rebased onto latest
main. Two rounds of upstream integration:ClientMessagearm 31 forset_brightness, colliding with myset_fps— renumbered mine to 32 (proto + firmwareARM_SET_FPS+ regeneratedledmapper_pb.ts); both coexist.tests/ffi.rs(its OSC test block vs my fps test block, and the import list) — kept both. The autoscaler and OSC hooks coexist cleanly in the render loop /loop().Notes
playback_state).@ledmapper/protocolflat types don't carry these arms yet (same as the perf/brightness arms — web-local innet/proto.ts)..fxbshader effects (the heavy, variable-cost path); the cheap fixed built-in patterns are unchanged.🤖 Generated with Claude Code
Closes-Linear: FUG-82 (https://linear.app/fughilli/issue/FUG-82/autoscale-framerate)