Skip to content

Only point the session at NVIDIA when NVIDIA is driving the screen - #9483

Open
VykosMolt wants to merge 2 commits into
omacom:quattrofrom
VykosMolt:fix/nvidia-env-on-hybrid
Open

VykosMolt wants to merge 2 commits into
omacom:quattrofrom
VykosMolt:fix/nvidia-env-on-hybrid

Conversation

@VykosMolt

@VykosMolt VykosMolt commented Aug 31, 2026 •

Copy link
Copy Markdown

NVIDIA session hints now follow the display detector instead of GPU presence alone. The detector combines cached PCI boot metadata with DRM connector wiring, avoiding lspci and NVIDIA queries that wake an offload GPU.

The existing omarchy-hw-nvidia-display helper now handles the reported iGPU-panel laptops, including a docked laptop with its lid closed and a G14 whose iGPU has no boot_vga attribute. A connected NVIDIA panel still selects NVIDIA; NVIDIA-only desktops retain driver hints when the monitor is off or behind a KVM. The Lua configuration gates NVD_BACKEND, LIBVA_DRIVER_NAME and __GLX_VENDOR_LIBRARY_NAME together. Reusing the upstream helper resolves the overlap with #11690.

Validation: 23 executable detector/Lua cases, the full CLI suite, ShellCheck and git diff --check pass on the branch merged with current quattro. The cases use synthetic sysfs trees and execute the real Lua configuration. The new lid-closed and monitor-off cases still need confirmation on matching hardware.

@kevinbsr

Copy link
Copy Markdown

Confirming this from the AMD+NVIDIA side (Dell G15 5515, Ryzen 7 5800H + RTX 3060 Mobile, iGPU-primary), and raising one hardware shape that I think the "drives a display" question answers differently than intended.

The patch is the right shape. Reading connector status out of the driver's cached state is the detail that matters — every other way of asking resumes the card, which is the trap the existing comment in nvidia.lua already warns about for lspci. Gating on it is strictly better than today on this machine.

The measurement, for whoever needs the cost quantified. I reported this in #8989: removing the two variables took the system from 23.7 W to 10.7 W. One correction worth carrying over, because I got it wrong first: the env does not stop the dGPU from reaching D3cold when idle — I restored it and the card still slept 100% of the time. What it costs is waking the card for anything that decodes video, and then keeping it awake. It is "wakes on use", not "never sleeps", so the delta shows up under a video workload rather than at an idle desktop.

The case I want to flag: laptops where every external output is muxed to the dGPU. On this machine the internal panel is the only output the iGPU owns:

card0  vendor=0x10de  driver=nvidia
     card0-DP-1        disconnected
     card0-HDMI-A-1    disconnected
card1  vendor=0x1002  driver=amdgpu
     card1-eDP-1       connected

Undocked, the detector correctly answers no. Docked, it answers yes — DP-1 is an NVIDIA connector — and the session names NVIDIA again, including for the clients on the still-AMD internal panel. That is arguably correct for windows on the external screen, but hl.env is session-wide, so the laptop display pays for it too, and the ~10 W comes back whenever a monitor is plugged in.

This layout is common on gaming laptops: the built-in panel is wired to the iGPU and the external ports are hardwired to the discrete card, with the compositor still compositing on the iGPU and doing PRIME output offload.

So the question this answers is "is NVIDIA driving an output", where the thing the env should follow is closer to "is NVIDIA driving the output the compositor renders on". I don't think that blocks this PR — undocked hybrid laptops are the common case and this fixes them. But it may be worth either narrowing the detector to the primary/compositing GPU, or saying in the comment that docking deliberately opts the session back in, so the next person measuring 10 W while docked finds the answer instead of filing a fourth issue.

Happy to test a revision on this hardware, docked and undocked, if that would help.


Reported with the help of Claude Code.

nvidia.lua sets NVD_BACKEND, LIBVA_DRIVER_NAME and __GLX_VENDOR_LIBRARY_NAME
whenever omarchy-hw-nvidia succeeds, and that detector answers "is there an
NVIDIA GPU in this machine", which is true of every hybrid laptop. Those
variables are session-wide, so on a hybrid laptop every GL and VA-API client is
pointed at a discrete card that is not driving anything, while the panel hangs
off the integrated GPU.

The card is normally in runtime suspend, so the first GL application to start
has to wake it, and it stays powered while anything is using it. On this laptop,
an Arrow Lake iGPU driving eDP-1 with an RTX 5070 Ti Mobile suspended:

  glxinfo, discrete card suspended
    without the variables      75 ms, 85 ms      card left suspended
    with the variables       2675 ms, 2733 ms    card woken

  glxinfo, discrete card already awake
    without the variables      80 ms
    with the variables        153 ms

and what each one actually selects:

    without   Intel, Mesa Intel(R) Graphics (ARL)
    with      NVIDIA GeForce RTX 5070 Ti Laptop GPU

The Intel renderer is the one holding the display.

omarchy-hw-nvidia-drives-display answers the narrower question, and nvidia.lua
now requires both. NVIDIA counts when it has a connector reporting `connected`
and no other card has a connected built-in panel. The panel rule is what keeps a
docked hybrid laptop off NVIDIA: on many of them the external ports are wired to
the discrete card, so docking lights up an NVIDIA connector while the compositor
carries on rendering on the integrated GPU, and these variables are session-wide.
A laptop whose panel is on the NVIDIA card, and a desktop with no panel at all,
still count. Connector status is served from the driver's cached state, so asking
costs 3ms and leaves a suspended card suspended, in keeping with the rest of
these detectors.

This does not stop anyone rendering on the discrete card. It stops the session
being pointed at it by default on a machine where it is not driving the screen,
which is what PRIME offload is for.
@VykosMolt
VykosMolt force-pushed the fix/nvidia-env-on-hybrid branch from 77162c9 to 553e772 Compare September 10, 2026 14:50
@VykosMolt

Copy link
Copy Markdown
Author

You're right, and I'd put it more strongly than "arguably correct": hl.env is session-wide, so on that layout the internal panel pays for a card it never renders on. Thanks for the correction on the measurement too — "wakes on use", not "never sleeps", is the accurate framing and I've taken it.

Force-pushed a narrower detector. It now answers no if a built-in panel — eDP, LVDS or DSI — on a non-NVIDIA card is connected, whatever the NVIDIA connectors say. A panel on another card means the compositor is rendering there, and docking doesn't move it.

By hardware shape:

  • your G15 undocked — no, unchanged
  • your G15 docked — was yes, now no
  • panel wired to the NVIDIA card — yes, unchanged
  • desktop, monitor on NVIDIA, integrated card idle — yes, unchanged
  • desktop driving monitors from both cards — yes, unchanged

Desktops are untouched, because the rule keys on a built-in panel and they don't have one. The last case is the one I left alone deliberately: there's no cheap sysfs answer to which card the compositor picked, and answering no there would be a regression for people who plugged their monitor into the NVIDIA card on purpose.

The docked case is now asserted in hw-nvidia-test.sh — it was asserted the other way round, which is the bug you found — alongside panel-on-NVIDIA, desktop-with-idle-integrated-card and monitors-on-both. 21 assertions, all passing; the previous detector fails the docked one.

The offer to test docked and undocked would be very welcome, if it still stands.

@Hazakins

Copy link
Copy Markdown

The narrowed built-in-panel detector gives the right answer on an AMD+NVIDIA machine, and I want to add one thing the gate does not cover.

Hardware: Framework Laptop 16, Ryzen AI 9 HX 370 / Radeon 890M (amdgpu) driving eDP-2 plus a Samsung G95C over a Thunderbolt dock; RTX 5070 graphics module present, its own connectors disconnected. Omarchy 4.0.3, Hyprland 0.56.2-2, kernel 7.2.3-arch1-3, mesa 26.2.2, nvidia 610.57.04. With stock nvidia.lua, LIBVA_DRIVER_NAME=nvidia + __GLX_VENDOR_LIBRARY_NAME=nvidia were exported session-wide; Chrome decoded video on the dGPU and handed frames to the amdgpu compositor (flashing playback, and a GPU-process SIGTRAP in Meet on 2026-09-09). Pinning the session to radeonsi/mesa fixed both. I have not built this PR — I run an equivalent local override — so this is a datapoint on the rule, not a patch test.

The eDP-on-another-card rule asks the right question. On this box both versions of the gate answer "no" (the NVIDIA connectors are disconnected), so it does not separate them here; but @TijmenvandenBan's case on #8215 (NVIDIA driving DP-2 while Chromium still renders on renderD129) shows the display owner and the renderer can disagree, and keying on the built-in panel's card sidesteps that.

What the env vars do not cover: on this box the dGPU never reaches D3cold while any GTK4 app or Chrome is open, because the Vulkan loader enumerates every ICD. Measured with gtk4-layer-demo alone: 7 fds on /dev/nvidia0, 4 on nvidiactl, 2 on the NVIDIA render node, with LIBVA_DRIVER_NAME already set to radeonsi. Pinning VK_DRIVER_FILES to the RADV ICD takes it to zero with no renderer change. Worth considering alongside the VA-API/GLX selection.


Disclosure: this diagnosis and write-up were produced by Claude (Fable 5.1, via Claude Code) working on my laptop; the measurements are from my machine and I reviewed the text before posting.

@kevinbsr

Copy link
Copy Markdown

Tested on the G15, both ways. The narrowed detector does what you said it would.

Hardware, docked (real, not simulated): two external displays plugged in, both on NVIDIA connectors, internal panel on the AMD card.

card0-DP-1        connected     (NVIDIA)
card0-HDMI-A-1    connected     (NVIDIA)
card1-eDP-1       connected     (amdgpu)
first version current
G15 docked (real hardware) yes no
G15 undocked no no

Undocked is the same machine with the two external connectors reading disconnected — that was its real state earlier today, and I re-ran it through OMARCHY_DRM_CLASS_PATH to get both detectors against the identical tree. Docked is live hardware with three displays actually lit.

Session env with the current detector's answer, docked: LIBVA_DRIVER_NAME=radeonsi, __GLX_VENDOR_LIBRARY_NAME=mesa, and glxinfo reports the compositor on radeonsi/renoir. That is the outcome the patch is for.

One thing the docked case changes about my earlier power claim, which I should correct. Docked, the dGPU sits at runtime_status=active / power_state=D0 and stays there — it has to, it is driving both external outputs. So the 23.7 W → 10.7 W I quantified is an undocked number. Docked, the card is awake no matter what these two variables say, and the patch is not buying that back.

That does not weaken the change; it just narrows what it buys. Docked, the win is correctness rather than watts: clients render on the card the compositor actually composites on, instead of being pushed to a card whose frames then have to cross back. Undocked, it is both.

For completeness, the control case still answers correctly here: a fake tree with the panel on the NVIDIA card and the Intel connectors disconnected returns yes, so the rule does not regress laptops wired the other way.


Reported with the help of Claude Code.

@kevinbsr

Copy link
Copy Markdown

@Hazakins I reproduced your gtk4-layer-demo measurement exactly, and then got the opposite answer on the part that matters. Posting both because I think the two halves of that finding travel differently.

The fd count reproduces to the digit. Dell G15 5515, Ryzen 7 5800H + Radeon Vega (Cezanne, amdgpu) driving the panel, RTX 3060 Mobile (GA106M) present. nvidia 610.57.04, mesa 26.2.2, Hyprland 0.56.2, kernel 7.2.4-arch1-2 — same driver and mesa as yours.

/dev/nvidia0 /dev/nvidiactl NVIDIA render node AMD render node
as shipped 7 4 2 1
VK_DRIVER_FILES → RADV 0 0 0 1

7 / 4 / 2, exactly your numbers, with LIBVA_DRIVER_NAME=radeonsi already exported. Pinning the ICD zeroes them and does not move the renderer — the AMD node stays at 1 either way. So "the Vulkan loader opens the NVIDIA device even when nothing asks it to" is confirmed on a second machine.

Where it diverges: here those fds do not cost D3cold. Same session, undocked, with Hyprland, Brave, Electron and Spotify all holding /dev/nvidiactl, the card read runtime_status=suspended / power_state=D3cold with 397 minutes of accumulated runtime_suspended_time. An earlier pass on this machine (2026-08-31) reached the same conclusion from the other direction: with all four env vars restored to nvidia, the dGPU still slept 100% of the time.

So on GA106M an open fd is not a wakelock. On your RTX 5070 it evidently is. Same driver branch, different silicon — worth flagging so nobody generalises the sleep claim from the fd claim, because the fd claim does generalise and the sleep one apparently does not.

And the fix has a cost worth naming. Pinning VK_DRIVER_FILES to RADV makes the discrete card invisible to every Vulkan client, not just the ones you wanted to keep off it. On this machine that meant Steam titles silently rendering on the iGPU with no error and no indication — which is a worse failure than the thing it fixes, because it is quiet. Anyone applying this on a laptop that also games wants nvidia-offload (or an equivalent that re-exports the vars) on those launchers, or they will not notice until they wonder why the framerate halved.

None of this argues against your datapoint — on hardware where the card genuinely will not sleep, the trade flips. I just would not want the loader-enumerates observation and the never-sleeps conclusion shipped as one finding.


Measured with the help of Claude Code.

@Hazakins

Copy link
Copy Markdown

@kevinbsr thanks for re-running it — and you're right that the two halves need to travel separately. I re-measured this morning so the sleep claim rests on a number rather than on my earlier wording.

On the RTX 5070 Laptop the fds do hold the card awake. env -u VK_DRIVER_FILES gtk4-layer-demo, reading only power/runtime_status: suspended → active within 2 s of launch, active for the whole two-minute run with runtime_suspended_time frozen, suspended again about 12 s after the demo exited. The demo was the only holder (/dev/nvidia0 ×7, nvidiactl ×4, NVIDIA render node ×2). Same driver branch as yours (610.57.04, mesa 26.2.2, kernel 7.2.3).

One question that might reconcile the two machines: in your D3cold reading the holders had /dev/nvidiactl open. Did the 3060 also stay in D3cold while gtk4-layer-demo itself was running with its seven /dev/nvidia0 handles? nvidiactl is the control node; nvidia0 is the per-GPU one. If your card sleeps even then, it's silicon/firmware; if it wakes, it's about which node gets opened, and the "fd claim" and the "sleep claim" line up again.

On the cost — agreed, and under this pin it's worse than a missing nvidia-offload. Under the pin, the prime-run variables alone don't bring the card back: with __NV_PRIME_RENDER_OFFLOAD=1 __VK_LAYER_NV_optimus=NVIDIA_only set, vulkaninfo --summary still lists only the Radeon 890M, because VK_DRIVER_FILES keeps the loader from ever reading the NVIDIA ICD. The per-app override has to re-point VK_DRIVER_FILES at nvidia_icd.json as well. With that in a wrapper used as the Steam launch option (<wrapper> %command%), the setting survives the Steam runtime: pressure-vessel imports it as /usr/lib/pressure-vessel/overrides/share/vulkan/icd.d/nvidia_icd.json inside the container. (Honest limit: both titles I have installed are native OpenGL builds, so what I verified end to end is the GL side — libGLX_nvidia mapped, the game holding the 5070 — plus that env rewrite; I haven't yet run a Vulkan/Proton title through it.) We also list installed Steam games that lack the wrapper at login, so a forgotten one doesn't stay quiet.

So for anyone reading along: the pin is only worth it on hardware where the enumeration actually keeps the card awake, and only together with a per-app override that resets VK_DRIVER_FILES, not prime-run alone.


Disclosure: this diagnosis and write-up were produced by Claude (Opus 5, via Claude Code) working on my laptop; the measurements are from my machine and I reviewed the text before posting.

@Hazakins

Copy link
Copy Markdown

Follow-up on the limit I mentioned: I've now run a Proton title through it. Among Us (Windows-only, Proton Experimental, SteamLinuxRuntime_4) with <wrapper> %command% as the launch option rendered on the RTX 5070 — DXVK's d3d11.dll/dxgi.dll → winevulkan → the NVIDIA ICD, VK_DRIVER_FILES inside the container rewritten to /usr/lib/pressure-vessel/overrides/share/vulkan/icd.d/nvidia_icd.json, and the game holding the card at ~56 % load. So the per-app override survives Proton as well as the native OpenGL titles.

One trap for anyone copying this: Steam writes a newly edited launch option to localconfig.vdf lazily (about two minutes here), so a script that reads the file right after you set it will report the game as not opted in. ~/.local/share/Steam/logs/console_log.txt ("Game process added : AppID …") shows the command Steam actually launched.


Disclosure: this diagnosis and write-up were produced by Claude (Opus 5, via Claude Code) working on my laptop; the measurements are from my machine and I reviewed the text before posting.

@VykosMolt

Copy link
Copy Markdown
Author

@kevinbsr thanks for running both detectors on the G15 — docked on live hardware is exactly the case the tests can only simulate. The correction lands too: docked, the card is awake for its own outputs anyway, so there the change buys correctness rather than watts.

@Hazakins the loader opening every ICD is a real finding, but it's a separate mechanism from the one this PR gates, and your 5070 and kevinbsr's 3060 disagree on whether it costs D3cold. Pinning VK_DRIVER_FILES also hides the dGPU from every Vulkan client and fails quietly for games unless each launcher resets it. That trade depends on the hardware, so I'd rather keep it out of this PR and let it be its own issue.

@kevinbsr

Copy link
Copy Markdown

@Hazakins ran your exact test on the 3060, with a clean sleeping baseline. The card sleeps right through it. So on this hardware it is silicon/firmware, not about which node gets opened — the two halves stay separate.

env -u VK_DRIVER_FILES gtk4-layer-demo, undocked (both NVIDIA connectors disconnected), reading power/runtime_status and runtime_suspended_time:

baseline, no demo :  30006 ms of sleep in 30 s   = 100 % asleep
demo running      :  72151 ms of sleep in 90 s   =  80 % asleep
  +15s  active
  +30s  active
  +45s  suspended     <- back in D3cold with the demo still up
  +60s  suspended
  +75s  suspended
  +90s  suspended

Descriptors held by the demo for that whole window: /dev/nvidia0 ×7, /dev/nvidiactl ×4, NVIDIA render node ×2 — identical to your numbers. The card wakes for the enumeration, then returns to D3cold about 40 s later and stays there while every one of those handles is still open.

So your nvidiactl vs nvidia0 hypothesis does not explain the difference here: the per-GPU node is open seven times and the GA106M sleeps anyway. Same driver branch (610.57.04), same mesa (26.2.2). The divergence looks like the silicon or its firmware, not the node.

Why my earlier reply was not a clean measurement, for the record. My first D3cold reading came from ordinary apps holding nvidiactl, not from the demo holding nvidia0 — you were right that it was not comparable. My first two attempts at redoing it were also invalid: once docked, where the card is awake for its own outputs regardless, and once undocked but without a sleeping baseline. Which turned up something worth knowing on its own:

Undocking does not restore runtime suspend on this machine. After the external displays came out, both NVIDIA connectors read disconnected, yet runtime_suspended_time stayed frozen for over four minutes — the card had not slept for a single millisecond since the monitors were first plugged in. Only a logout/login brought it back. If anyone else measures a hybrid laptop that has been docked during the session, that alone will make the card look permanently awake.

One more confound for anyone reproducing this: btop with show_gpu_info = "Auto" polls the card through NVML and holds it up for as long as it is open.


Measured with the help of Claude Code.

@remydw

remydw commented Sep 12, 2026

Copy link
Copy Markdown

Verified on separate hardware — this detector gives the right answer where a boot_vga-based one does not.

Machine: ROG Zephyrus G14 GA403WW, Ryzen AI 9 HX 370 (Radeon 890M) + RTX 5080 Max-Q, Omarchy 4.0.3-1, Hyprland 0.56.2, mesa 26.2.2, Chrome 153.

NVIDIA  0000:64:00.0  class 0x030000  boot_vga=0
        DP-1, HDMI-A-1, eDP-1 -> all disconnected
AMD     0000:65:00.0  class 0x038000  boot_vga ABSENT
        eDP-2 + DP-3 connected (compositor renders on this card)
  • omarchy-hw-nvidia-drives-display → exit 1 here (no NVIDIA connector is connected, and the built-in panel belongs to another card). Correct.
  • I then ran the session state this PR produces — all three variables unset — through headed Chrome with --vmodule=vaapi*=2,video_decoder*=1 on a YouTube page: VaapiVideoDecoder() initialises three times, zero vaInitialize failures, zero eglCreateImage failed lines (the current default produces 2482 of them in ~15 s), the GPU process maps only libgallium, the video region shows real frames (0.0 % black, 63.9 % inter-frame change) and the dGPU stays suspended. CPU is 29.3 % of the Chrome tree versus 50.5 % for the software-decode fallback.
  • Gating all three variables rather than only LIBVA_DRIVER_NAME is the part I would keep: leaving __GLX_VENDOR_LIBRARY_NAME=nvidia in place still points XWayland GLX clients at the discrete card.

One implementation note: not calling hl.env at all is the right shape for this fix, because Hyprland cannot unset a variable — hl.env requires a string, and an empty string is not equivalent to unset. LIBVA_DRIVER_NAME="" makes libva attempt to load a driver named "" (vaInitialize failed: unknown libva error), after which Chromium silently software-decodes while chrome://gpu still reports "Video Decode: Hardware accelerated".

Independent context, measurements and the review of #10589 are in #8726.

@VykosMolt

Copy link
Copy Markdown
Author

@remydw thanks. The G14 is the third machine in this thread and the first where the NVIDIA card has its own eDP-1 present but disconnected, which is the case the built-in-panel rule had to get right without leaning on boot_vga. Your Chrome trace is the user-visible half of what kevinbsr measured in watts: zero eglCreateImage failures against 2482 with the current default, and the dGPU staying suspended throughout.

Agreed on all three variables, and on unset rather than blank. hl.env cannot express "not set", and LIBVA_DRIVER_NAME="" sends libva looking for a driver named "", so the detector decides before hl.env is called and the NVIDIA branch is skipped entirely when it answers no.

Tally for whoever queues this, all iGPU-panel AMD+NVIDIA laptops, all answering no with the current detector: Dell G15 5515 docked and undocked (kevinbsr, live hardware both ways), Framework 16 with an RTX 5070 module (Hazakins, equivalent local override), ROG G14 GA403WW (remydw). The NVIDIA-drives-the-panel case is the one the tests cover.

@srgonzale

Copy link
Copy Markdown

Tested on Intel+NVIDIA hybrid: TigerLake-H + RTX 3050 Mobile

Hardware:

  • iGPU: Intel TigerLake-H GT1 UHD Graphics (card2, vendor 0x8086) — eDP-1 connected
  • dGPU: NVIDIA GA107M GeForce RTX 3050 Mobile (card1, vendor 0x10de) — no DRM connectors at all

Detector results:

  • omarchy-hw-nvidia → exit 0 (NVIDIA GPU present)
  • omarchy-hw-nvidia-drives-display → exit 1 (no NVIDIA connector connected, Intel panel is the built-in display)

Before the patch:

  • LIBVA_DRIVER_NAME=nvidia, NVD_BACKEND=direct, __GLX_VENDOR_LIBRARY_NAME=nvidia set session-wide
  • Chromium video playback issues (flashing, corruption, or decode failures)

After the patch:

  • All three NVIDIA env vars unset — env | grep -iE "libva|nvidia|glx|nvd" returns nothing
  • Chromium video playback works correctly, hardware decode on Intel/Mesa as expected
  • Fix persists across logout/login

The detector correctly identifies this as a hybrid laptop where the iGPU drives the panel, and skips the NVIDIA session env. Video works as intended.

@allisonmahmood

Copy link
Copy Markdown

Tested the detector on Intel + NVIDIA where the NVIDIA card does have connected outputs: i7-11800H TigerLake-H GT1 (card2, i915, boot_vga=1, eDP-1) + RTX 3060 Mobile (card1, nvidia 615.71.09, boot_vga=0, dock outputs DP-3 and DP-4 connected). Hyprland 0.56.2 renders on the Intel node and blits to the NVIDIA outputs.

  • omarchy-hw-nvidia → 0
  • omarchy-hw-nvidia-gsp → 0
  • omarchy-hw-nvidia-drives-display (this PR) → 1

So the foreign_panel branch does what the comment says: a docked laptop with NVIDIA-wired ports is correctly left on the iGPU. With the current release this machine gets LIBVA_DRIVER_NAME=nvidia and Chromium web apps and Beeper (Electron) go fully transparent after scrolling embedded video; the GPU process shows nvidia_drv_video.so loaded while rendering on renderD129.

One gap in the predicate: if the lid is closed while docked, eDP-1 reports disconnected, foreign_panel stays 0, and the script returns 0 even though the compositor still renders on the Intel card. Gating on which card has boot_vga=1 (or on the render device the compositor picked) would avoid depending on connector state. Happy to test a revision.

Filed by Claude Fable 5.1 via Claude Code, on behalf of the account owner.

@omarchybot

Copy link
Copy Markdown
Collaborator

Reviewed at 553e772. This no longer merges: #11690 landed on quattro on 2026-09-25 and fixes the same bug a different way, with a boot_vga-based bin/omarchy-hw-nvidia-display gating LIBVA_DRIVER_NAME and __GLX_VENDOR_LIBRARY_NAME in the same block of default/hypr/nvidia.lua this changes. #13659 is also open, extending that detector to prefer connected DRM connectors. Choosing between them is for the maintainer, so nothing was pushed here.

What was run. On a disposable Omarchy worker, test/shell.d/hw-nvidia-test.sh at this head passes all 21 assertions. Separately, each tree's real nvidia.lua was run against fake sysfs trees for the hardware reported in this thread, and the three detectors were compared directly. The ROG G14 shape @remydw described (AMD iGPU with class 0x038000 and no boot_vga file, panel on AMD) exports direct nvidia nvidia on the fork point and still does on current quattro, because omarchy-hw-nvidia-display answers yes when no card claims boot_vga; this head exports nothing. So quattro does not fully fix the bug, and this branch covers a case it misses.

shape quattro (#11690) #13659 this PR
G15 docked: externals on NVIDIA, panel on AMD no yes no
G14: iGPU without boot_vga, panel on AMD yes no no
Intel+3060 docked, lid closed, eDP-1 reads disconnected no yes yes
NVIDIA-only desktop, no monitor detected at login yes yes no
desktop with iGPU as boot_vga, monitor on NVIDIA no yes yes

"yes" means the session is pointed at NVIDIA. The first three rows should be "no". The lid-closed row rests on @allisonmahmood's report that eDP-1 reads disconnected with the lid shut, which a worker cannot show; if it holds, both connector-based rules get it wrong and boot_vga gets it right. The fourth row is a behaviour change from today for a desktop whose monitor is off or behind a KVM when Hyprland starts.

Not checked. The full suite did not run, since the branch cannot merge as it stands. The second opinion (Codex Medium) did not run: the reviewer's daily limit was reached, so this review is Claude Opus 5.5's alone.

Waiting on the maintainer: whether to carry this PR's built-in-panel rule onto quattro beside #11690's boot_vga check, take #13659, or close this one. Any of those needs this branch rebuilt on current quattro.

@VykosMolt

VykosMolt commented Oct 8, 2026 •

Copy link
Copy Markdown
Author

Merged current quattro and rebuilt the change around the existing omarchy-hw-nvidia-display helper in 59bf730, so it no longer conflicts with #11690 or adds a duplicate detector. The cached DRM wiring rule now handles a closed docked lid; a connected NVIDIA panel overrides the foreign-panel rule, and NVIDIA-only desktops keep their hints with no detected monitor. All three hints are gated together. All 23 real detector/Lua fixture cases, full CLI and ShellCheck pass. The newly added hardware shapes are fixture coverage, not new physical-GPU measurements.

@greptile-apps

greptile-apps Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

[High impact] Adds multi-account support for AI agent CLIs with new session routing.

The PR appears safe to merge, with a non-blocking fix recommended for pending account cleanup.

Findings

  1. P2 Failed additions leave login files ▶

Summary

The supplied comparison adds cached NVIDIA display detection and gates session-wide NVIDIA driver hints on that result. It also includes broader changes to agent accounts, updates, dictation, wallpapers, and desktop controls.

  • NVIDIA selection covers connected panels, desktop outputs, and no-output fallbacks.
  • Hybrid users receive a reboot request to remove previously inherited driver hints.
  • One non-blocking cleanup issue remains: failed account registration can leave pending login files behind.

Intent recorded: VykosMolt describes keeping session-wide NVIDIA hints off on docked hybrid laptops whose built-in panel belongs to another card.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[NVIDIA GPU detected?] -->|No| B[Do not set NVIDIA hints]
  A -->|Yes| C[Read cached PCI and DRM state]
  C --> D[Connected NVIDIA built-in panel?]
  D -->|Yes| E[Set NVIDIA driver hints]
  D -->|No| F[Built-in panel on another card?]
  F -->|Yes| B
  F -->|No| G[NVIDIA output connected or NVIDIA-only DRM?]
  G -->|Yes| E
  G -->|No| H[Use connected-output and boot fallback]
Loading

Reviews (1) · Last reviewed commit: "Unify cached NVIDIA display detection ac..." · Reviewed by Greptile

Comment on lines +219 to +222
else
home=""
fail "$account"
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Failed additions leave login files

If saving the account registry fails, register() moves the signed-in home back to .pending. This branch then clears home, so the exit trap cannot delete it. The failed addition leaves login files behind with no account entry to list or remove them.

Keep home set on failure so the existing cleanup trap can remove the pending directory.

Suggested change
else
home=""
fail "$account"
fi
else
fail "$account"
fi

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This finding concerns the shared upstream implementation. The tested fix is in #14656. The actual add command now cleans the pending login after registry-save failure. Independent source review and the final branch account, real mise dispatch, autoswitch, usage, panel, and CLI suites pass. Keeping this thread open while that corrective PR awaits integration.

@omarchybot omarchybot removed the bug Something isn't working label Oct 8, 2026
@omarchybot

Copy link
Copy Markdown
Collaborator

Read again at 59bf730, which is now one commit on current quattro changing bin/omarchy-hw-nvidia-display, default/hypr/nvidia.lua and test/shell.d/hw-nvidia-test.sh. It merges cleanly and builds on the helper #11690 added rather than conflicting with it. Nothing was run on a worker this time.

The classification is unsettled, so this has not been verified yet. Claude Opus 5.5 reads it as a hardware compatibility fix: on AMD or Intel + NVIDIA laptops whose panel is on the iGPU, the session is pointed at NVIDIA's VA-API and GLX drivers, which breaks video in Chromium. Codex Medium, classifying from the pull request alone, reads it as an enhancement, a deliberate change in behaviour rather than a fix. There is a case for that reading: beyond the hybrid-laptop fix, this head stops setting NVD_BACKEND whenever the detector answers no, makes DRM connector state rather than boot_vga the main signal, and keeps the NVIDIA hints on NVIDIA-only desktops with no monitor detected. The bug label from the previous review has come off until the two agree.

What happens next: a third model or the maintainer settles the classification. If it is settled as a fix, this head is then reproduced on a worker, and because the bug depends on the hardware it also needs someone with a matching machine to confirm it at the full SHA 59bf730. The test reports earlier in this thread were made against older heads. #13659 is still open and fixes the same bug a different way.

@mudiam

mudiam commented Oct 21, 2026

Copy link
Copy Markdown

Regression check on real hardware at 59bf7302: a laptop whose internal panel runs on the NVIDIA card. The result is unchanged from the shipped behaviour, as intended.

Machine: Lenovo ThinkPad P17 Gen 1 in discrete mode. NVIDIA Quadro T1000 Mobile (TU117GLM, Turing, so GSP) is the only GPU on the PCI bus and in DRM (card1, vendor 0x10de). The internal panel is card1-eDP-1 (connected); DP-1..3 and HDMI-A-1 are disconnected. nvidia-open-dkms 615.78.08, Omarchy 4.0.6-1, Hyprland 0.56.2-4.

Omarchy 4.0.6 as shipped This PR
omarchy-hw-nvidia-display on the real sysfs exit 0 exit 0
default/hypr/nvidia.lua, run through lua against the real sysfs direct nvidia nvidia direct nvidia nvidia
What the live session exports today NVD_BACKEND=direct, LIBVA_DRIVER_NAME=nvidia, __GLX_VENDOR_LIBRARY_NAME=nvidia (same, per the row above)
  • bash test/shell.d/hw-nvidia-test.sh: 23/23 pass.
  • The bin/omarchy-hw-nvidia-display and default/hypr/nvidia.lua hunks apply cleanly to the shipped 4.0.6 files.

On this machine every lid/DPMS state falls into nvidia_panel, or into nvidia_cards && !other_cards if the panel ever reported disconnected. So the closed-lid and monitor-off paths can't change the result on a discrete-mode laptop. The docked-hybrid lid-closed case the PR still needs confirmation for requires an iGPU-panel machine, which this isn't (and this machine's iGPU is disabled in the current mode).

So there's no regression for an NVIDIA-panel laptop: it keeps all three hints.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants