Skip to content

feat(linux): route mutter to the eGPU and declare the VA-API decode stack - #114

Merged
inkatze merged 3 commits into
mainfrom
feat/gpu-primary-and-vaapi
Aug 15, 2026
Merged

feat(linux): route mutter to the eGPU and declare the VA-API decode stack#114
inkatze merged 3 commits into
mainfrom
feat/gpu-primary-and-vaapi

Conversation

@inkatze

@inkatze inkatze commented Aug 14, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes the two causes of slow video and game performance on the server host (T2 MacBook Pro + RX 580 eGPU), found while diagnosing why the machine underperformed its macOS days. The internal Radeon Pro 560X is deliberately clamped to its lowest DPM state for thermal headroom, but as boot_vga it was also mutter's default primary GPU, so the entire desktop and any game launched without DRI_PRIME rendered at 214 MHz. The udev rule file gains a companion rule tagging the RX 580 mutter-device-preferred-primary; the clamp stays, reduced to scanning out the built-in panel, and detaching the eGPU falls back to today's behavior. The media package block additionally declares the VA-API decode stack: mesa-va-drivers (virtual in resolute, provided by the already-installed mesa-libgallium, so a documented no-op here that still pulls the provider on a fresh host) and intel-media-va-driver (genuinely absent until now).

How to review: roles/linux/files/udev/30-amdgpu-pm.rules (the new rule and its reasoning), roles/linux/defaults/main.yml (media block), roles/linux/tasks/power.yml (comment, PS-1).

  • Verified on the host: mutter logs GPU /dev/dri/card0 selected primary given udev rule after one gdm restart; udevadm verify passes on the rule file; the 16:00 Ansible run installed the Intel driver and resolved the virtual package cleanly.
  • Tooling: yamllint, ansible-lint (production profile), playbook syntax-check, gitleaks (branch scope) all pass.
  • Pending sign-off: PS-1 (power.yml deploy-task comment now names the primary-GPU side effect) — see the collapsed checklist.
Audit record

Lens coverage

Lens Findings Notes
Correctness, logic, edge cases none udev matching verified against the live host; virtual-package install path empirically validated by the 16:00 run; one connector-glob candidate refuted (declined log #2)
Security none no secrets or injection surface; no write-time security triggers touched; gitleaks clean on the branch range
Error handling and failure modes none eGPU-detached fallback (tag matches nothing → boot_vga) documented in the rule and verified by reasoning against mutter's selection logic
Performance none the change is itself the performance fix; the built-in-panel copy path is a documented tradeoff of the retained clamp
Concurrency / state 1 candidate, declined tag-application timing vs mutter startup; empirically refuted (declined log #1)
Naming, readability, structure 1 candidate, declined pm-named file now carries display policy; review-mode high bar, header acknowledges it (declined log #3)
Documentation 1 power.yml deploy-task comment omitted the new primary-GPU side effect → PS-1
Tests / verification none no udev test harness in the repo; substituted udevadm verify (Success 1, Fail 0) plus live-host verification; gap recorded as an observation
Cross-file consistency shared with Documentation the PS-1 finding is the cross-file drift; no other sibling patterns broken

Auto-applicable

# Finding Tool + rule Fix Commit
none

Agent-resolvable

# Finding Test Before → after CI Brief alignment Commit
none (bucket unavailable: pass ran brief-less)

Needs sign-off

# Finding Fix applied Route reason Commit Checklist ID
1 power.yml's deploy-task comment describes the rule file as clamp-only, but deploying it now also changes which GPU renders the desktop added a sentence naming the primary-GPU tag and when it takes effect single unambiguous fix, not tool-grounded; comment is the only in-file record of a consequential deploy side effect f29999e PS-1

Needs human judgment

# Fork Ladder record Outcome Options
none

Declined log

# Finding Validation summary Rationale Where re-raisable
1 rule-file comment says "logout/login, not just a udev reload" without explaining the tag lands via change uevents handler confirmed reload-only; every practical path (boot=add, hotplug=add, logout=teardown change events) applies the tag before mutter starts, confirmed by the one-restart success on the host advice is behaviorally correct and complete; mechanism detail adds length without changing any action PR review
2 KERNEL=="card*" also matches connector nodes (card0-DP-9), potentially tagging them empirically no tag leakage on connectors; mutter reads only the card device; identical shape to the deployed, working clamp rule no functional impact; tightening would diverge from the sibling rule for no behavior change PR review
3 file named 30-amdgpu-pm.rules now carries display-policy content header rewritten to name both halves; no tool flags it review-mode high bar: rename churn (defaults var, stale-file cleanup task) not justified by a naming nit PR review

Pending sign-off

  • PS-1 power.yml deploy-task comment now names the mutter primary-GPU side effect · commit f29999e
    • Route reason: single recommended fix; the comment is the only in-file record of a consequential deploy side effect
    • Reject with: git revert f29999e

Pass summary

Standalone mode, base origin/main (fetched). Brief-less by user direction (branch is ad-hoc host work; four spec bundles were Ready so detection was ambiguous), which made the Agent-resolvable bucket unavailable for the pass. Discovery ran inline (declared: 2 files, ~52 changed lines, mostly prose/config — inside the skill's inline threshold). Tooling: yamllint ✓, ansible-lint ✓, syntax-check ✓, gitleaks branch-scope ✓; udevadm verify ✓ on the rule file. Full-history gitleaks reports 57 pre-existing findings outside this branch — recorded as an observation, not a branch finding. No reverts, no degraded tooling, no queued forks. Observations committed: gitleaks-history triage gap, udev-rules verification gap.

…tack

The internal Radeon Pro is deliberately clamped to its lowest DPM state,
and as boot_vga it was also mutter's primary GPU, so the whole desktop
(and any game launched without DRI_PRIME) rendered at 214 MHz. Tag the
RX 580 eGPU mutter-device-preferred-primary so rendering happens on the
card running at full clocks; the clamp stays, reduced to scanning out
the built-in panel, and detaching the eGPU falls back to today's
behaviour.

Also declare the VA-API drivers in the media block: mesa-va-drivers
(virtual in resolute, provided by the already-installed mesa-libgallium)
and intel-media-va-driver (genuinely absent), and record the ssh
render-node permission trap that made the decode stack look missing.
@inkatze
inkatze marked this pull request as ready for review August 15, 2026 21:35
@inkatze
inkatze merged commit 8476e81 into main Aug 15, 2026
10 of 12 checks passed
@inkatze
inkatze deleted the feat/gpu-primary-and-vaapi branch August 15, 2026 21:35
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.

1 participant