From f71ac0e03d1aece2447bfeb11a2f698c5c2d4cca Mon Sep 17 00:00:00 2001 From: 1okko <15377594951@189.cn> Date: Tue, 29 Sep 2026 22:33:42 +0800 Subject: [PATCH] ui: show egpu icon while remote big model is inferring --- .../ui/sunnypilot/onroad/hud_renderer.py | 13 +++++++++++++ .../selfdrive/ui/widgets/qnn_runtime_badge.py | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/openpilot/selfdrive/ui/sunnypilot/onroad/hud_renderer.py b/openpilot/selfdrive/ui/sunnypilot/onroad/hud_renderer.py index f8e425773..0746fb7bd 100644 --- a/openpilot/selfdrive/ui/sunnypilot/onroad/hud_renderer.py +++ b/openpilot/selfdrive/ui/sunnypilot/onroad/hud_renderer.py @@ -17,6 +17,7 @@ from openpilot.selfdrive.ui.sunnypilot.onroad.turn_signal import TurnSignalContr from openpilot.selfdrive.ui.sunnypilot.onroad.circular_alerts import CircularAlertsRenderer from openpilot.selfdrive.ui.sunnypilot.onroad.speed_renderer import SpeedRenderer from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus +from openpilot.selfdrive.ui.widgets.qnn_runtime_badge import RuntimeBadgeCache from openpilot.selfdrive.ui.onroad.hud_renderer import HudRenderer, UI_CONFIG, FONT_SIZES, COLORS, CRUISE_DISABLED_CHAR from openpilot.system.ui.lib.application import gui_app from openpilot.system.ui.lib.multilang import tr @@ -36,6 +37,8 @@ class HudRendererSP(HudRenderer): self.turn_signal_controller = TurnSignalController() self.circular_alerts_renderer = CircularAlertsRenderer() self.speed_renderer = SpeedRenderer() + self._qnn_runtime = RuntimeBadgeCache() + self._qnn_egpu_icon = gui_app.texture("icons_mici/chestnut_green.png", 120, 88) self._torque_bar = TorqueBar(scale=3.0, always=True) self.pcm_cruise_speed: bool = True @@ -60,6 +63,7 @@ class HudRendererSP(HudRenderer): self.turn_signal_controller.update() self.circular_alerts_renderer.update() self.speed_renderer.update() + self._qnn_runtime.update() def _get_icbm_status(self): if not self.pcm_cruise_speed and ui_state.sm['carControl'].enabled: @@ -128,6 +132,14 @@ class HudRendererSP(HudRenderer): def _draw_current_speed(self, rect: rl.Rectangle) -> None: self.speed_renderer.render(rect) + def _draw_qnn_egpu_icon(self, rect: rl.Rectangle) -> None: + if not self._qnn_runtime.remote_inferring(): + return + icon = self._qnn_egpu_icon + rl.draw_texture_ex(icon, rl.Vector2(rect.x + rect.width - UI_CONFIG.border_size - icon.width, + rect.y + rect.height - UI_CONFIG.border_size - icon.height), + 0.0, 1.0, rl.WHITE) + def _render(self, rect: rl.Rectangle) -> None: super()._render(rect) @@ -144,3 +156,4 @@ class HudRendererSP(HudRenderer): self.turn_signal_controller.render(rect) self.circular_alerts_renderer.render(rect) self.rocket_fuel.render(rect, ui_state.sm) + self._draw_qnn_egpu_icon(rect) diff --git a/openpilot/selfdrive/ui/widgets/qnn_runtime_badge.py b/openpilot/selfdrive/ui/widgets/qnn_runtime_badge.py index 23b7c0f15..cd6da7cbb 100644 --- a/openpilot/selfdrive/ui/widgets/qnn_runtime_badge.py +++ b/openpilot/selfdrive/ui/widgets/qnn_runtime_badge.py @@ -79,6 +79,8 @@ class RuntimeBadgeCache: self._worker = None self._next_read = -float('inf') self._results = queue.Queue(maxsize=1) + self._last_remote_outputs = None + self._last_remote_change_at = -float('inf') @property def pending(self): @@ -89,6 +91,10 @@ class RuntimeBadgeCache: self._raw = self._results.get_nowait() if isinstance(self._raw, dict) and self._raw.get('schema') == 'qnn-host-status-v1': self._seen = True + remote_outputs = self._raw.get('remote_outputs') + if type(remote_outputs) is int and remote_outputs != self._last_remote_outputs: + self._last_remote_outputs = remote_outputs + self._last_remote_change_at = self.clock() except queue.Empty: pass @@ -116,6 +122,19 @@ class RuntimeBadgeCache: self._consume() return describe_runtime(self._raw, self.clock(), seen=self._seen) + def remote_inferring(self): + """Return true only while bounded remote output counters are advancing.""" + self._consume() + raw = self._raw + if not isinstance(raw, dict) or raw.get('schema') != 'qnn-host-status-v1': + return False + stamp = raw.get('updated_boottime') + now = self.clock() + remote_outputs = raw.get('remote_outputs') + return (type(stamp) in (int, float) and math.isfinite(stamp) and 0 <= now - stamp <= 3 and + raw.get('remote_started') is True and type(remote_outputs) is int and remote_outputs > 0 and + now - self._last_remote_change_at <= 2 and not raw.get('failure_reason')) + class QnnRuntimeBadge: """Shared renderer for Mici and the standard SP HUD extension points."""