Skip to content

Commit 6355ed5

Browse files
jpietekclaude
andcommitted
Set up the hardware service before the Auto-UV dialog opens
The setup dialog reads GPU identity and limits through the daemon, so a fresh or upgraded install (0.6.x Python-daemon era, stale AUR daemon) opened it with a misleading generic "NVIDIA GPU" and no limits — the exact state that scared users away from the one prompt that would fix it. The install/update/migrate prompt now runs when Setup Auto Undervolt is clicked, before the dialog; the remaining unavailable-info fallback text names the service and the fix instead of "NVML read-only info unavailable". README: drop the GIF footnote and add the stock RTX 5080 baseline (2734 MHz at 341 W) next to the tier results for scale. Live-verified on real hardware: daemon stopped -> Setup click shows the service prompt first and no dialog; accepting reinstalls the service and the dialog then lists the real GPU and limits. Focused Qt suites passed on this change; the full-suite run is deferred to an idle host (known environmental Qt deadlock, aggravated by a live Auto-UV scan). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 08fbe98 commit 6355ed5

4 files changed

Lines changed: 48 additions & 23 deletions

File tree

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
- **Balanced** — undervolt and maintain clock. RTX 5080: 850 mV · 2639 MHz · 267 W.
2626
- **Performance** — undervolt and overclock. RTX 5080: 915 mV · 2980 MHz · 310 W.
2727

28+
For scale: the same RTX 5080 at stock runs 2734 MHz at **341 W** under the
29+
same load. The factory curve burns 74 W more than Balanced for 4% clock —
30+
that is the inefficiency Auto-UV removes.
31+
2832
Verified RTX 5080 examples; every GPU differs. Pre-optimized targets are
2933
included for RTX 30, 40, and 50 series cards.
3034

@@ -33,9 +37,6 @@ automatic undervolting & overclocking. Adaptive per-game tuning targets a
3337
chosen pre-frame-generation FPS; the optional overlay shows PC latency and live
3438
FPS.
3539

36-
The GIF uses PenguinBurner's real Qt interface with simulated scan data; live
37-
Auto-UV uses the same UI while testing your GPU.
38-
3940
## Install
4041

4142
```bash

tests/test_ui_window_actions.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ def win(qapp, monkeypatch):
6060

6161
def test_start_scan_cancelled(win) -> None:
6262
window, monkeypatch = win
63+
monkeypatch.setattr(
64+
window_mod,
65+
"ensure_daemon_ready_for_privileged_action",
66+
lambda **_kwargs: True,
67+
)
6368
monkeypatch.setattr(window_mod, "select_scan_tuning", lambda **k: None)
6469
fake = _FakeController()
6570
window.scan_controller = fake
@@ -107,29 +112,36 @@ def test_full_scan_shows_tier_progress_but_selected_profile_scan_hides_it(win) -
107112
assert window.auto_uv_tier_progress.widget.isHidden()
108113

109114

110-
def test_start_scan_runs_daemon_migration_gate_before_scan(win) -> None:
115+
def test_start_scan_runs_daemon_gate_before_the_setup_dialog(win) -> None:
116+
# The setup dialog reads GPU identity/limits through the daemon: the
117+
# install/update prompt must fire BEFORE the dialog opens, or a fresh
118+
# install shows a misleading generic GPU with no limits.
111119
window, monkeypatch = win
112-
gate_calls = []
113-
monkeypatch.setattr(window_mod, "select_scan_tuning", lambda **k: {"gpu_index": 0})
114-
monkeypatch.setattr(window_mod, "persist_runtime_gpu_index", lambda idx: int(idx))
115-
monkeypatch.setattr(window_mod, "scan_command", lambda options: ["echo", "scan"])
120+
order = []
116121

117122
def fake_gate(**kwargs):
118-
gate_calls.append(kwargs)
123+
order.append(("gate", kwargs["action_label"]))
119124
return True
120125

126+
def fake_dialog(**_kwargs):
127+
order.append(("dialog", None))
128+
return {"gpu_index": 0}
129+
121130
monkeypatch.setattr(
122131
window_mod,
123132
"ensure_daemon_ready_for_privileged_action",
124133
fake_gate,
125134
)
135+
monkeypatch.setattr(window_mod, "select_scan_tuning", fake_dialog)
136+
monkeypatch.setattr(window_mod, "persist_runtime_gpu_index", lambda idx: int(idx))
137+
monkeypatch.setattr(window_mod, "scan_command", lambda options: ["echo", "scan"])
126138
fake = _FakeController()
127139
window.scan_controller = fake
128140

129141
window.start_scan()
130142

131-
assert gate_calls
132-
assert gate_calls[0]["action_label"] == "Starting Auto-UV"
143+
assert order[0] == ("gate", "Setting up Auto-UV")
144+
assert order[1] == ("dialog", None)
133145
assert fake.started
134146

135147

ui/features/tuning/tuning.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,9 +430,16 @@ def _power_limit_set_probe_applicable(power: object | None) -> bool:
430430
)
431431

432432

433+
_NVML_INFO_UNAVAILABLE_TEXT = (
434+
"GPU limits unavailable: the PenguinBurner background hardware service "
435+
"is not responding. Close this dialog and click Setup Auto Undervolt "
436+
"again to install or repair it (one admin prompt)."
437+
)
438+
439+
433440
def auto_uv_nvml_info_text(info: AutoUvNvmlInfo | None) -> str:
434441
if info is None:
435-
return "NVML read-only info unavailable"
442+
return _NVML_INFO_UNAVAILABLE_TEXT
436443

437444
rows = [
438445
_power_limit_text(info),
@@ -443,7 +450,7 @@ def auto_uv_nvml_info_text(info: AutoUvNvmlInfo | None) -> str:
443450
_power_limit_set_text(info.power_limit_set_supported),
444451
]
445452
text = "\n".join(row for row in rows if row)
446-
return text or "NVML read-only info unavailable"
453+
return text or _NVML_INFO_UNAVAILABLE_TEXT
447454

448455

449456
def power_limit_set_supported(gpu_index: int) -> bool:

ui/window.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,21 @@ def show_about(self) -> None:
367367
def start_scan(self) -> None:
368368
if self._workflow_running():
369369
return
370+
# The setup dialog reads GPU identity and limits through the daemon,
371+
# so the service must be installed/updated BEFORE the dialog opens —
372+
# otherwise a fresh or upgraded install shows a misleading generic
373+
# "NVIDIA GPU" with no limits (the exact state that scares users off
374+
# the one action that would fix it).
375+
if not ensure_daemon_ready_for_privileged_action(
376+
QtWidgets=self.QtWidgets,
377+
parent=self.window,
378+
log=self.log_view.append,
379+
action_label="Setting up Auto-UV",
380+
# The scan streams through the daemon; a stale daemon without this
381+
# capability must land in the repair prompt, not fail at scan start.
382+
required_capabilities=("scan-stream-v1",),
383+
):
384+
return
370385
options = select_scan_tuning(
371386
QtCore=self.QtCore,
372387
QtGui=self.QtGui,
@@ -384,16 +399,6 @@ def start_scan(self) -> None:
384399
f"Could not save selected GPU index: {exc}",
385400
)
386401
return
387-
if not ensure_daemon_ready_for_privileged_action(
388-
QtWidgets=self.QtWidgets,
389-
parent=self.window,
390-
log=self.log_view.append,
391-
action_label="Starting Auto-UV",
392-
# The scan streams through the daemon; a stale daemon without this
393-
# capability must land in the repair prompt, not fail at scan start.
394-
required_capabilities=("scan-stream-v1",),
395-
):
396-
return
397402
options = {**options, "gpu_index": int(self.gpu_index)}
398403
# Bring the scan into view: the live runs/curve are on the Auto-UV tab.
399404
self.tabs.setCurrentIndex(self.auto_uv_tab_index)

0 commit comments

Comments
 (0)