We Recovered MangoHud GPU 99% on Deck Idle Menu Despite menu_fps_cap Receipt Pass - 2026 Case Study
This is a synthesized case study—a field pattern from July 2026 Steam Deck OLED fest demos where menu_fps_cap_receipt_v1.json showed pass: true (Steam overlay or in-engine counter held 60 FPS on the title screen) but MangoHud still reported GPU utilization ~99% after fifteen minutes idle. Players posted fan noise and heat comments; producers assumed the FPS cap “already shipped.”
There are no invented Wh/min figures, no fake refund percentages, and no named studio turnaround. Recovery means separating FPS overlay truth from GPU busy-wait truth, then filing gpu_idle_smoke_pass on the receipt stack.
Pair with menu FPS opinion, Deck OLED idle battery help, Unity vSync menu cap help, and 16 Deck tools. Planned help: MangoHud GPU 99% despite receipt.
Non-repetition note: The opinion argues you should cap menu FPS. The June battery help targets Wh/min drain. This case study covers receipt pass vs MangoHud disagreement—two metrics, one false green gate.
Why this matters now (July 2026)
- Deck OLED battery audits — Teams added
menu_fps_caprows after May opinion traffic without GPU idle smoke. - MangoHud in facilitator kits — Playtesters paste HUD screenshots; producers trust graphs over receipts.
- 3D menus behind 2D UI — Full scene still renders under static title cards.
- Post-processing on idle — Bloom/tone mapping runs at menu cap but GPU stays busy.
- Fest refund language — “Runs hot” tags appear beside crash rows in refund dashboards.
Direct answer: Add gpu_idle_smoke_pass to menu_fps_cap_receipt_v1.json only after a 15-minute idle MangoHud log on installed Deck build shows GPU below your team threshold—and fix menu scene render load, not only targetFrameRate.
Beginner quick start — what recovered means
Recovered here means:
- Reproduced high GPU% on installed Deck build at main menu—not editor.
- Explained why FPS cap receipt was green while GPU was red.
- Shipped static menu or disabled background render loop.
- Logged
mangohud_idle_recovery_receipt_v1.jsonwithgpu_idle_smoke_pass: true. - Reduced new “fan/heat” discussion comments for seven days on same
build_label(qualitative).
Not recovered: Claiming “60 FPS” fixes Deck power without MangoHud proof.
Two metrics beginners must separate
| Metric | What it measures | Can lie when |
|---|---|---|
| FPS overlay | Frames presented per second | CPU-bound UI cap while GPU still draws full 3D backdrop |
| MangoHud GPU % | Graphics engine busy on GPU | Menu capped but scene complexity unchanged |
| Wh/min (battery help) | Power draw | Different gate—run after GPU idle green |
Working dev rule: menu_fps_cap_receipt proves frame pacing; gpu_idle_smoke_pass proves idle render cost.
Starting state (typical wrong assumptions)
| Layer | Belief | Reality |
|---|---|---|
| Receipt | menu_fps_cap: pass |
Only checked overlay FPS |
| Menu scene | “2D UI, cheap” | 3D environment + post FX still running |
| Deck QA | One-minute glance | Heat needs 15-minute idle |
| BUILD_RECEIPT | Single perf row |
Missing compat vs power split |
| Marketing | “Runs at 60 on Deck” | True for counter, false for GPU graph |
Root cause pattern (synthesized)
| Mechanic | MangoHud symptom | FPS overlay |
|---|---|---|
| Uncapped render scale | GPU high at “low” FPS | May still show 60 |
| Animated 3D backdrop | GPU pegged | 60 if vsync locked |
| Full-screen UI redraw | GPU busy | Stable FPS |
| vSync on 120 Hz display | Misread as cap success | 120 not 60 |
| runInBackground + menu audio | Periodic GPU wake | FPS dips ignored |
Often combined after branch promotion without menu scene diff.
Timeline (five working days — pattern timing)
| Day | Focus | Output |
|---|---|---|
| D1 | Repro Deck installed + MangoHud log | idle_menu_mangohud.log |
| D2 | Scene audit (3D, PP, scale) | menu_render_audit.md |
| D3 | Static menu / disable backdrop render | Patch build |
| D4 | 15-minute idle re-test | GPU below threshold |
| D5 | Receipt + BUILD_RECEIPT row | mangohud_idle_recovery_receipt_v1.json |
Gates H1–H6 (idle GPU recovery)
| Gate | Name | Pass criterion |
|---|---|---|
| H1 | Installed repro | Deck build, not editor |
| H2 | Metric split documented | FPS vs GPU columns in audit |
| H3 | Menu render diet | Backdrop static or culled |
| H4 | 15-minute MangoHud | GPU% under team max (document threshold in receipt) |
| H5 | Receipt stack | gpu_idle_smoke_pass on menu_fps_cap_receipt |
| H6 | Promotion | mangohud_idle_recovery_receipt_v1.json committed |
H4 blocks fest_public when RED—even if H5 was green on old build.
menu_fps_cap_receipt_v1.json (extended fields)
{
"schema": "menu_fps_cap_receipt_v1",
"build_id": "deck-fest-2026-rc7",
"menu_target_fps": 60,
"deck_overlay_fps_idle": 60,
"menu_fps_cap_pass": true,
"gpu_idle_smoke_pass": false,
"mangohud_gpu_percent_15min_peak": 99,
"idle_test_minutes": 15,
"device": "steam_deck_oled",
"notes": "FPS pass before H4 fix — do not promote"
}
After recovery, set gpu_idle_smoke_pass: true and record new mangohud_gpu_percent_15min_peak from your measured log—not this article’s numbers.
mangohud_idle_recovery_receipt_v1.json
{
"schema": "mangohud_idle_recovery_receipt_v1",
"build_id": "deck-fest-2026-rc8",
"paired_menu_fps_cap_receipt": "release-evidence/perf/menu_fps_cap_receipt_v1.json",
"gates": {
"H1_installed_repro": "pass",
"H2_metric_split": "pass",
"H3_menu_render_diet": "pass",
"H4_mangohud_15min": "pass",
"H5_receipt_stack": "pass",
"H6_promotion": "pass"
},
"fixes_applied": [
"disabled_menu_environment_tick",
"render_scale_0.85_menu_only",
"static_menu_camera"
],
"promotion_allowed": true
}
MangoHud capture protocol (15 minutes)
- Install fest build from Steam (not desktop shortcut to editor).
- Launch MangoHud with logging enabled per Deck battery resource.
- Sit on main menu—no input except one brightness check at minute 5.
- Archive log with
build_labelvisible on title screen photo. - Compare minute 0–1 vs minute 10–15—spikes at loop boundaries implicate animated UI or rotating backdrop.
Do not conflate with gameplay GPU profile—export separate gameplay_mangohud.log.
menu_render_audit.md (template)
# Menu render audit — build deck-fest-2026-rc7
- 3D environment active behind UI: YES (fail H3)
- Post-processing stack on menu: bloom + tonemap
- Render scale menu: 1.0 (gameplay 1.0)
- UI CanvasGroup updates every frame: YES
- Particles in menu: YES
- targetFrameRate: 60, vSyncCount: 0
- Steam overlay FPS: 60
- MangoHud GPU 15m peak: 99%
Fix patterns that worked (synthesized)
| Fix | When to apply |
|---|---|
| Static menu camera | Rotating hero mesh caused pegged GPU |
Disable environment process_mode |
3D world ticked while UI idle |
| Lower menu-only render scale | GPU bound, FPS already capped |
| Remove menu bloom | Post stack cost at “60 FPS” |
| Cap UI animation rate | Spine/UI skeletal updates every frame |
| Scene policy swap | Unity MenuFpsCap pattern + render diet |
Honest limit: Some engines need separate menu scene without gameplay assets loaded—profile size, not only FPS.
Engine notes (menu idle GPU)
| Engine | Common menu GPU trap |
|---|---|
| Unity URP/HDRP | Full scene loaded; PP volume active on menu |
| Godot 4.5 | SubViewport 3D preview running |
| Unreal | Menu map still has skylight + dynamic shadows |
| Construct NW.js | Less common—check WebGL if Deck via Proton |
| Ren'Py | Usually CPU—verify if 3D layers added |
Cross-link menu FPS opinion engine tables for FPS; this case study adds GPU load column mentally.
Relationship to Deck OLED battery help
| Topic | OLED battery help | This case study |
|---|---|---|
| Primary metric | Wh/min | MangoHud GPU % |
| Receipt field | idle_power_smoke_pass |
gpu_idle_smoke_pass |
| Player complaint | Battery drain | Fan / heat / “GPU max” |
| Order | Run after GPU idle green or in parallel | Diagnose receipt false green |
File both passes before October fest if reviews cite power and heat.
BUILD_RECEIPT row (split compat vs power)
{
"build_id": "deck-fest-2026-rc8",
"deck_compat_smoke": "pass",
"menu_fps_cap": "pass",
"gpu_idle_smoke": "pass",
"idle_power_smoke": "pending",
"evidence": "release-evidence/perf/mangohud_idle_recovery_receipt_v1.json"
}
Thursday row review should flag when menu_fps_cap green but gpu_idle_smoke missing.
Wednesday smoke extension
Add to Wednesday demo smoke Deck lane:
- [ ] Main menu 60s no input—MangoHud screenshot
- [ ]
gpu_idle_smoke_passnotpendingon receipt - [ ] Separate gameplay smoke still run
Binary smoke alone missed this pattern—extend, do not replace.
Case vignettes (synthesized)
Vignette A — FPS receipt green, rotating hero
Team filed menu_fps_cap_pass from Steam overlay. MangoHud flatlined 99%—menu hero mesh rotated with realtime lights. Fix: static camera + baked lighting on menu only. Time: two engineering days.
Vignette B — vSync “success” at 120 Hz
Deck panel ran 120 Hz; targetFrameRate = 60 but GPU still pushed frames for full 3D menu. Receipt claimed cap; MangoHud disagreed. Fix: menu scene unload + render_scale drop. Paired Unity vSync help.
Vignette C — Producer promoted on FPS only
fest_public shipped; Discord heat thread in 48 hours. Rollback; added H4 gate. Lesson: never promote on menu_fps_cap_pass alone in July 2026 audits.
Facilitator README snippet
## Deck idle menu test
- Sit main menu 15 minutes with MangoHud logging
- File bugs with GPU% screenshot + build_label
- Tag: deck-gpu-idle (not deck-fps-cap)
- Do not mark PASS from Steam FPS overlay alone
Troubleshooting
| Observation | First check |
|---|---|
| GPU 99%, FPS 60 | H3 render diet |
| GPU drops after click Start | Menu-only issue—good signal |
| GPU high in gameplay too | Different playbook—not this URL |
| MangoHud missing on Deck | Use built-in perf overlay + battery help Wh/min |
| Receipt pass from Windows only | H1 fail—retest installed Deck |
Promotion checklist
- [ ]
mangohud_idle_recovery_receipt_v1.jsoncommitted - [ ]
gpu_idle_smoke_pass: trueon menu_fps_cap receipt - [ ] 15-minute log archived
- [ ]
menu_render_audit.mdlists pre/post fixes - [ ] BUILD_RECEIPT splits compat vs power columns
- [ ] Forward help linked when published
FAQ
Is 99% GPU always a bug?
On idle menu for fest demos—treat as RED until explained (cinematic exception must be documented).
Can we skip MangoHud?
Use another GPU graph tool—but measure GPU utilization, not FPS alone.
Does menu FPS cap useless?
No—it is necessary not sufficient. Keep both gates.
Proton vs native?
Repro on player path—Proton titles still file Deck receipts.
Key takeaways
menu_fps_cap_receiptpass does not imply idle GPU health.- 15-minute MangoHud logs catch backdrop render loops.
gpu_idle_smoke_passbelongs on the same receipt stack.- Static menu discipline fixes most synthesized patterns.
- Planned MangoHud help complements this case study URL.
Evidence folder layout
release-evidence/perf/deck-idle/
idle_menu_mangohud.log
menu_render_audit.md
menu_fps_cap_receipt_v1.json
mangohud_idle_recovery_receipt_v1.json
screenshots/
mangohud_minute_15.png
steam_overlay_fps_60.png
gameplay_mangohud.log # separate baseline
Friday Block 5 should verify gpu_idle_smoke did not regress when art swaps menu video loops.
Team threshold policy (you define the number)
This case study does not prescribe “GPU must be under 30%.” Micro-studios pick thresholds based on genre:
| Studio type | Example policy |
|---|---|
| 2D narrative | Peak 40% at 15m idle menu |
| 3D action fest slice | Peak 55% with static menu |
| Cinematic menu | Document exception + shorter idle test |
Record chosen max in mangohud_idle_recovery_receipt_v1.json as gpu_percent_threshold_team and mangohud_gpu_percent_15min_peak from your log.
Godot 4.5 menu diet sketch
# MenuRoot.gd — disable 3D backdrop while UI shown
func _ready() -> void:
if MenuState.is_title:
$WorldEnvironment3D.process_mode = Node.PROCESS_MODE_DISABLED
$MenuBackdrop.visible = false
Engine.max_fps = 60
Pair with scene unload if gameplay subscene stayed in tree from last session debug.
Unity menu scene policy sketch
// MenuSceneController.cs — swap profiles on load
void OnEnable() {
QualitySettings.vSyncCount = 0;
Application.targetFrameRate = 60;
DisableGameplayVolume(); // URP/HDRP
RenderSettings.fog = false; // example diet
}
void OnDisable() {
GameplayFramePolicy.Restore();
}
Log applied flags into menu_render_audit.md—receipt auditors read markdown, not IL.
Playtest CSV columns (facilitators)
| Column | Example |
|---|---|
build_label |
deck-fest-2026-rc8 |
surface |
deck_installed |
menu_idle_minutes |
15 |
mangohud_gpu_peak |
48 |
steam_overlay_fps |
60 |
tag |
deck-gpu-idle |
Stops “runs fine” rows without GPU numbers.
Opinion F-gates vs H-gates (crosswalk)
| Menu FPS opinion F-gate | This case study H-gate |
|---|---|
| F1 cap exists | H5 menu_fps_cap_pass |
| F2 battery check | Pair OLED battery help |
| F3 Deck verify | H1 installed Deck |
| F4 receipt filed | H5 + H6 |
| F5 branch policy | BUILD_RECEIPT split rows |
Adding H4 closes the gap F-gates left open in the field.
When to escalate to engine vendor or Valve
Escalate only after H3:
- GPU pegged with empty menu scene (only UI)—possible driver/Proton issue.
- MangoHud disagrees with multiple tools—attach logs +
build_id. - Threshold met on Windows but fails only Deck—document Proton version.
Do not open Valve ticket with “FPS capped” subject without GPU log attachment.
Post-mortem questions (after fest)
- Did we promote on overlay FPS alone?
- Did art add looping video backdrop after perf sign-off?
- Did
gpu_idle_smokecolumn exist in BUILD_RECEIPT before July? - Will Help #12 publish before next Deck playtest wave?
Stream and refund narrative
Heat clips spread faster than crash logs—producers should search social for fan spin keywords when gpu_idle_smoke was never filed. Refund dashboard taxonomy can add perf_heat tag separate from crash to route threads to this receipt folder.
Producer one-pager (copy to Notion)
## Deck idle menu — July 2026 gate
PASS requires ALL:
1. menu_fps_cap_receipt.menu_fps_cap_pass = true
2. menu_fps_cap_receipt.gpu_idle_smoke_pass = true
3. mangohud_idle_recovery_receipt.promotion_allowed = true
4. 15m log archived under release-evidence/perf/deck-idle/
FAIL if facilitators send only Steam overlay FPS screenshot.
Art and design handoff rules
| Request | Perf impact |
|---|---|
| Looping menu video backdrop | Often H3 fail |
| Realtime rim light on static logo | GPU peg |
| Full-screen blur on UI | Post stack cost |
| “Use gameplay environment for menu” | Loads heavy assets |
Art leads sign menu_render_audit.md before fest art lock—engineering should not discover rotating hero mesh on promotion day.
Compatibility with Steam Deck Verified
Deck verified submission checks compatibility lists; this case study checks idle power perception. A title can pass Verified checkbox rows while still failing H4—file both evidence types in partner packets.
Rollback discipline
If H4 fails on fest_public after promotion:
- Pull public depot or disable fest visibility per your runbook.
- Post known-issue with
build_labelbefore heat thread spikes. - Ship rc+1 with
mangohud_idle_recovery_receiptGREEN. - Re-run Wednesday smoke Deck lane only—do not rerun entire metadata sprint unless store copy changed.
Rollback without receipt update recreates the same false green gate next week.
Lessons for small teams without a perf engineer
Assign producer as receipt owner and one gameplay programmer as MangoHud operator—split roles prevent “engineering said 60 FPS” disputes in Discord. Use a single #deck-idle-evidence thread with pinned log links; do not scatter screenshots across marketing channels where context is lost. When budget allows, borrow a Deck OLED for 48 hours before fest lock—not the morning of store page publish.
Document gpu_percent_threshold_team in the same wiki page as menu FPS opinion branch policy so new contractors do not reintroduce full 3D menus before October traffic. Treat gpu_idle_smoke_pass as a promotion gate equal to menu_fps_cap_pass—not an optional stretch goal for Deck builds.