Files
gen1recomp/tests/modkit
Shane McGovern 7e2307f58c Use spare CPU cores to remove in-game hitches on low-power devices (#2872)
* Use spare CPU cores to remove in-game hitches on low-power devices

Per-frame game logic and drawing are cheap; the remaining stalls on
low-power handhelds are one-off main-thread hitches from chip SFX/cry
synthesis, RED++ atlas recolouring, image decodes and the require shim.
Move those onto background threads, each with a synchronous fallback so
behaviour is identical when threads are unavailable (POKEPORT_NO_THREAD=1,
no love.thread, worker failure).

Also adds an F3 frame-time overlay and POKEPORT_GAME_PROF headless
profiling to measure these costs.

* Address code review: shared WorkerLane, F3 gating, decode/epoch fixes

- Extract src/core/WorkerLane.lua (worker lifecycle, prioritised lanes,
  per-lane epochs, bounded LRU) and rebuild the SFX and atlas/decode
  prefetchers on it
- Keep decoded sprite sheets in every colour mode (the OBJ palette bake
  re-reads them), skip oversized decodes, and let palette changes drop
  only atlas bakes
- Only bump the SFX render epoch when the channel mix actually changes
- F3 overlay toggle no longer steals the key from rebinding screens or
  player bindings; profilers stop only when a quit really proceeds
- Require fast path: test hook instead of a hot-path counter
- Shared tests/drivers/perf_util.lua; drivers restore their patches

* WorkerLane: no budget leak on duplicate sends, keep priority on requeue

- Lane:pump only counts a job against the in-flight budget once per key
- requeueInflight puts entries back at the head of their own queue, so
  background hints no longer overtake front requests after a bump
- shutdown() keeps a fatally failed worker off
- Hiding the F3 overlay logs one summary line instead of a full block

* F3 overlay: last-120-frame stats, font-sized box, scale on large screens

* Prefetch: skip useless hints, no main-thread fallback, mix check vs worker config

- Don't queue decodes for sprite sheets whose Image and OBJ bake are cached
- Atlas hint is dropped (sync bake at build time) when the worker can't
  decode the tileset itself, instead of decoding on the main thread
- SFX epoch bump compares the live mix with what the worker was last
  configured with, replacing the load-time snapshot

* Sprite decode skip: raw-path cache check, never under RED++

* Gen 2 battles prefetch both parties' cries; sprite skip keyed by raw path

* Prefetch: skip cached tilesets outside RED++, log hint failures once

* Profiler: bench survives F3 hide, frame total excludes vsync; safer SFX pump, ordered requeue, tileset skip respects pending variants

* Profiler counts GPU stalls in present; water void-fill keeps tileset hint; README + test coverage

* Profiler vsync cap: measured cadence via RefreshRate, no per-frame allocation

* Use upstream's chip-worker prewarm for SFX/cries; drop our separate SFX worker

Our extra coverage (Gen 1 common SFX + party cries, both parties' battle
cries, lead move sounds, hit and battle SFX, Gen 2 bench cries) now goes
through ChipAudio.prewarmSfx/prewarmCry and a new Sound.prewarmMove.

* Skip decode hints for composed assets; share move cache key; drop dead demoteAll

* Drop dev-only profiling extras: POKEPORT_JITP hook and perf drivers

* README: name the worker threads POKEPORT_JIT leaves alone

* Profiler: count the pre-present vblank wait as present, log on NX quit

- time PresentSync.waitBeforePresent as "present" (the X11 GLX vblank wait
  lands there), so it is excluded like the wait inside present
- NX quit now emits the PROF summary / overlay line too
- love.quit's scripted check reads FrameProfiler.benchRequested, so
  POKEPORT_GAME_PROF=0 no longer counts as a bench run
- prefetchAtlas skips composed tileset sheets (Assets.isComposed)
- hit sounds defined once in EffectRegistry.HIT_SOUNDS, shared with the
  battle prewarm (each hit still gets its own copy)
- drop redundant obpPaths, dead FrameProfiler.visible and the unused
  Lane:bump requeue mode; restore applyOptions' doc comment
2026-10-12 08:38:45 +01:00
..
2026-07-19 16:18:18 -04:00
2026-07-19 16:18:18 -04:00
2026-07-19 16:18:18 -04:00
2026-08-24 07:52:05 -04:00
2026-09-26 20:39:59 -04:00
2026-07-19 16:18:18 -04:00