diff --git a/NOTES.md b/NOTES.md
new file mode 100644
index 0000000..314a126
--- /dev/null
+++ b/NOTES.md
@@ -0,0 +1,312 @@
+# DaVinci Resolve on Omarchy + RX 9060 XT — Working Configuration
+
+**Date solved:** 2026-05-02 (initial); 2026-05-03 (DRI_PRIME hybrid-GPU fix)
+**System:** Omarchy (Arch Linux), Hyprland 0.54.3, kernel 7.0.3, RX 9060 XT (Navi 44, gfx1200) + Intel UHD 770 hybrid
+
+## TL;DR — what is currently working
+
+DaVinci Resolve 21.0 beta launches and stays open with full UI on Color page. The working stack is:
+
+- ROCm **7.1.1** (NOT current 7.2.x) pinned from Arch Linux Archive
+- Resolve installed manually to `/opt/resolve` (no AUR PKGBUILD)
+- `HSA_OVERRIDE_GFX_VERSION=12.0.0` and `ROCR_VISIBLE_DEVICES=0` in the launcher
+- `DRI_PRIME=pci-0000_BB_DD_F` in the launcher — **explicit PCI tag, NOT `=1`** (see "Root cause" below)
+- `MESA_VK_DEVICE_SELECT=pci-0000_BB_DD_F` + `MESA_VK_DEVICE_SELECT_FORCE_DEFAULT_DEVICE=1` (Vulkan pin, defense-in-depth)
+- Hyprland windowrule v3 syntax (not deprecated `windowrulev2`)
+- snd-aloop kernel module + PipeWire bridge for audio
+- DeckLink → ALSA backend in Resolve config
+
+## Root cause
+
+There are TWO independent root causes that both have to be fixed for first launch to succeed:
+
+### 1. ROCm 7.2.x breaks Resolve on every AMD GPU
+
+OpenCL `clCreateContext` either fails outright or hangs on Color page. ROCm 7.1.1 is the last working release.
+
+- Upstream issue: https://github.com/ROCm/ROCm/issues/5982 (filed Feb 2026, still open)
+- CachyOS thread with the recipe: https://discuss.cachyos.org/t/davinci-resolve-amd-rocm-fails-without-downgrade/28036
+- NixOS RDNA4-specific report: https://github.com/NixOS/nixpkgs/issues/481483
+
+### 2. `DRI_PRIME=1` flips OpenGL to the iGPU on hybrid systems where Mesa already defaults to AMD
+
+On Intel iGPU + AMD dGPU systems where the monitor is plugged into the AMD card, Mesa's default OpenGL device is already the AMD card. `DRI_PRIME=1` means "give me the OTHER card relative to the default" — so it flips OpenGL to Intel. Resolve then has OpenGL on Intel and OpenCL on AMD, and CL/GL interop (`clCreateContext` with `CL_GL_CONTEXT_KHR`) fails. The log shows `OpenCL Context Manager failed to create context` and Resolve hangs on Color page.
+
+**Verify on any new box:**
+```bash
+glxinfo -B 2>/dev/null | grep -E 'OpenGL renderer|OpenGL vendor' # bare default
+DRI_PRIME=1 glxinfo -B 2>/dev/null | grep -E 'OpenGL renderer|OpenGL vendor' # what =1 picks
+DRI_PRIME=pci-0000_BB_DD_F glxinfo -B 2>/dev/null | grep -E 'OpenGL renderer|OpenGL vendor' # explicit
+```
+If bare returns AMD and `=1` returns Intel, you have this bug. The explicit PCI tag is always correct.
+
+The installer detects the AMD discrete card's PCI ID from `lspci` and bakes the tag into the launcher unconditionally whenever an AMD dGPU is present (no longer gated on hybrid status or switcheroo). switcherooctl is **not** used — it internally sets `DRI_PRIME=1` and inherits the same flip bug.
+
+## The install script
+
+`/home/q/Downloads/install-davinci-resolve.sh` — version 4.1 with 2026-05-03 patches:
+
+- **DRI_PRIME explicit PCI-tag pin** (replaces buggy `=1`) + **MESA_VK_DEVICE_SELECT** Vulkan pin — locks OpenGL/Vulkan to the AMD discrete GPU by bus address, unconditional whenever an AMD dGPU is present (no longer gated on hybrid status, switcheroo branch removed)
+- **Full glib-family symlink swap** — all five of `libglib-2.0`, `libgio-2.0`, `libgmodule-2.0`, `libgobject-2.0`, `libgthread-2.0` (was three; mismatch caused latent segfaults)
+- **Broader crash-marker grep** in `reset_stale_configs()` — recognises `Unsupported GPU Processing Mode`, `OpenCL Context Manager failed to create context`, `Failed to create OpenCL context`
+- **Fresh-install auto-wipe** of `~/.local/share/DaVinciResolve/{configs,logs}` whenever Resolve is being installed for the first time
+- **ROCm-downgrade error check** — `pacman -U` now aborts the install if the 7.1.1 packages fail to apply, instead of silently continuing on a broken stack
+- **Removed USB-dongle udev rule** and the prompt for it (Studio license dongle not in scope)
+- **Removed duplicate user-level `.desktop` entry** — system-level entry is patched to use the wrapper, user entry caused walker to show two "DaVinci Resolve" entries
+- **Dropped `stay_focused on` from the Resolve Hyprland rules** — it locked focus inside modal dialogs, felt like a trapped cursor
+
+Runs the full install end-to-end:
+
+1. System scan (kernel, GPU detection with gfx target + PCI bus address, audio, display, etc.)
+2. Pacman package install (minimal — Resolve bundles its own Qt5/libpng/etc.)
+3. **`install_rocm_pinned()`** — downloads ROCm 7.1.1 from Arch Linux Archive, installs via `pacman -U` (now `|| error` on failure so partial-downgrade can't go unnoticed), adds `IgnorePkg` to `/etc/pacman.conf [options]`
+4. Manual Resolve extraction (ZIP → .run → squashfs → /opt/resolve) with RPATH patching of every ELF. Bundled glib family — **all five** of `libglib-2.0`, `libgio-2.0`, `libgmodule-2.0`, `libgobject-2.0`, `libgthread-2.0` — replaced with system symlinks. Earlier installs only swapped three; mixing system glib with bundled libgobject (4-year version skew) risks segfaults on signal emit / type registration. Bundled `libc++`/`libc++abi` are deliberately KEPT (Resolve was compiled against specific ABI versions; replacing them crashes immediately).
+5. Audio fixes: DeckLink→ALSA, snd-aloop, PipeWire bridge, wireplumber default-sink exclusion
+6. Hyprland windowrule (v3 syntax)
+7. Desktop entries with `RESOLVE_INSTALL_LOCATION` placeholder substituted, system .desktop Exec lines pointed at the wrapper
+8. Launcher in `~/.local/bin/davinci-resolve` with HSA_OVERRIDE + ROCR_VISIBLE_DEVICES + **`DRI_PRIME=pci-` (explicit tag, derived from the AMD discrete card's PCI ID)** + MESA_VK_DEVICE_SELECT baked in. Single launcher template — switcheroo branch removed.
+9. **`reset_stale_configs()`** — clears `~/.local/share/DaVinciResolve/{configs,logs}` if any of these crash markers appear in `ResolveDebug.txt`: `Unsupported GPU Processing Mode`, `OpenCL Context Manager failed to create context`, `Failed to create OpenCL context`. Also fires unconditionally on fresh Resolve installs (`SCAN_RESOLVE_INSTALLED != true`) so any in-install failed-launch poison is wiped before the user ever opens the app.
+10. Final `clinfo -l` sanity check + ROCm pin verification
+
+Re-run any time:
+```bash
+~/Downloads/install-davinci-resolve.sh
+```
+
+## Key files / locations
+
+| File | Purpose |
+|------|---------|
+| `~/Downloads/install-davinci-resolve.sh` | The full installer (v4.1) |
+| `~/Downloads/fix-rocm-for-resolve.sh` | Standalone downgrade-only script (no install needed) |
+| `~/.local/bin/davinci-resolve` | Working launcher: HSA_OVERRIDE + ROCR_VISIBLE_DEVICES + DRI_PRIME PCI tag + MESA_VK pin |
+| `~/.local/bin/davinci-resolve-rusticl` | Rusticl OpenCL fallback (not currently working on RDNA4) |
+| `~/.local/bin/davinci-resolve-igpu` | Force iGPU (Intel) for testing |
+| `/usr/share/applications/DaVinciResolve.desktop` | The single Resolve menu entry; Exec rewritten to wrapper. No user-level davinci-resolve.desktop is created (would duplicate this in walker). |
+| `/usr/bin/davinci-resolve` | Convenience symlink to wrapper |
+| `/etc/pacman.conf` | Has `IgnorePkg = rocm-core rocm-device-libs rocm-llvm rocm-opencl-runtime comgr spirv-llvm-translator` in `[options]` |
+| `~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf` | PipeWire loopback bridge for audio |
+| `~/.config/wireplumber/wireplumber.conf.d/51-resolve-aloop-no-default.conf` | Keep aloop off default-sink rotation |
+| `/etc/modules-load.d/snd-aloop.conf` | Auto-load snd-aloop at boot |
+| `/etc/pki/tls -> /etc/ssl` | Symlink so Resolve's extras downloader finds Arch certs |
+
+## Currently pinned packages (do NOT update)
+
+```
+rocm-core 7.1.1-1
+rocm-device-libs 2:7.1.1-1
+rocm-llvm 2:7.1.1-1
+rocm-opencl-runtime 7.1.1-1
+comgr 2:7.1.1-1
+spirv-llvm-translator 21.1.3-1
+```
+
+## Critical "do not"
+
+- **Do not** install `opencl-amd` from AUR — conflicts with `rocm-opencl-runtime`, also has the broken 7.2 ABI.
+- **Do not** run `pacman -Syu` and accept rocm-* updates until ROCm 7.3+ ships with the Resolve fix.
+- **Do not** set `DRI_PRIME=1` on hybrid AMD systems — it's the OPPOSITE of what you want when Mesa already defaults to AMD (see Root cause #2). Always use the explicit PCI tag form `DRI_PRIME=pci-0000_BB_DD_F`.
+- **Do not** wrap the launcher in `switcherooctl launch` — it inherits the same `DRI_PRIME=1` bug.
+- **Do not** use `windowrulev2 = ...` in Hyprland config — deprecated in 0.53+. Use `windowrule = ACTION, match:KEY VALUE` form.
+- **Do not** add `stay_focused on` to the Resolve `drpopup` tag — it locks focus inside modal dialogs (Project Settings, Preferences, Render) and feels like a trapped cursor. Cosmetic-only rules (border_size, no_shadow, rounding, opacity) are safe.
+- **Do not** edit `~/.local/share/omarchy/` — it's git-managed by Omarchy and gets blown away on `omarchy update`.
+
+## When ROCm 7.3+ ships
+
+To lift the pin and try the official stack again:
+```bash
+sudo sed -i '/^IgnorePkg.*rocm-/d' /etc/pacman.conf
+sudo pacman -Syu
+~/.local/bin/davinci-resolve # test
+```
+
+If 7.3 also breaks Resolve, restore the pin via:
+```bash
+~/Downloads/fix-rocm-for-resolve.sh
+```
+
+## Recovery procedures
+
+### Resolve hangs / crashes
+
+The installer now wipes stale configs automatically on fresh installs and any time it sees a known crash marker, so this should rarely be needed manually. If you do need it:
+
+```bash
+# 1. Wipe stale config (preserves project DBs)
+mv ~/.local/share/DaVinciResolve/configs ~/.local/share/DaVinciResolve/configs.bak.$(date +%s)
+mv ~/.local/share/DaVinciResolve/logs ~/.local/share/DaVinciResolve/logs.bak.$(date +%s)
+
+# 2. Verify the OpenCL stack is intact
+clinfo -l # should show AMD gfx1200
+pacman -Q rocm-core rocm-opencl-runtime # should show 7.1.1
+grep IgnorePkg /etc/pacman.conf # should pin the rocm packages
+
+# 3. Verify the launcher pins to AMD (NOT DRI_PRIME=1)
+grep -E '^export (DRI_PRIME|HSA_OVERRIDE|ROCR_VISIBLE)' ~/.local/bin/davinci-resolve
+# DRI_PRIME must be a pci-... tag, never =1
+
+# 4. Re-launch
+~/.local/bin/davinci-resolve
+```
+
+Crash markers the installer recognises (any of these in `~/.local/share/DaVinciResolve/logs/ResolveDebug.txt` triggers the auto-wipe on next install run):
+- `Unsupported GPU Processing Mode` — original ROCm 7.2 symptom (no OpenCL device visible)
+- `OpenCL Context Manager failed to create context` — DRI_PRIME=1 flip / CL-GL interop failure
+- `Failed to create OpenCL context` — DVIP precursor of the above
+
+### Hyprland config errors after edit
+
+```bash
+hyprctl reload
+hyprctl configerrors # should be empty
+```
+If errors mention `windowrulev2`, replace with `windowrule = ACTION, match:KEY VALUE`. Examples in `~/.local/share/omarchy/default/hypr/`.
+
+### Desktop entry broken (app menu does nothing)
+
+Check for the literal placeholder:
+```bash
+grep RESOLVE_INSTALL_LOCATION /usr/share/applications/DaVinciResolve.desktop
+```
+If found, fix:
+```bash
+sudo sed -i \
+ -e "s|^Exec=.*|Exec=$HOME/.local/bin/davinci-resolve %U|" \
+ -e "s|RESOLVE_INSTALL_LOCATION|/opt/resolve|g" \
+ /usr/share/applications/DaVinciResolve.desktop
+sudo update-desktop-database
+```
+
+### Audio renders won't start
+
+snd-aloop must be loaded:
+```bash
+lsmod | grep snd_aloop # should show "snd_aloop"
+sudo modprobe snd-aloop # if missing
+```
+
+PipeWire bridge must be active:
+```bash
+ls ~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf
+ls ~/.config/wireplumber/wireplumber.conf.d/51-resolve-aloop-no-default.conf
+systemctl --user restart wireplumber pipewire pipewire-pulse
+```
+
+## Card compatibility — confidence tiers
+
+The script auto-detects gfx targets and applies the right HSA override for every card listed below. Confidence levels reflect how well-tested each tier is, not whether the script logic handles them.
+
+### ✅ Confirmed working (tested directly)
+
+| Card | gfx target | Auto HSA value |
+|------|-----------|----------------|
+| **RX 9060 / 9060 XT** (Navi 44) | gfx1200 | `12.0.0` |
+
+This is the only card where I've personally seen Resolve launch all the way to the Color page with this exact stack.
+
+### 🟢 Should work — natively supported by ROCm 7.1.1
+
+| Card | gfx target | Auto HSA value |
+|------|-----------|----------------|
+| **RX 9070 / 9070 XT** (Navi 48) | gfx1201 | `12.0.1` |
+| **RX 7900 / 7900 XT / 7900 XTX** (Navi 31) | gfx1100 | `11.0.0` |
+| **RX 7700 XT / 7800 XT** (Navi 32) | gfx1101 | `11.0.1` |
+| **RX 6800 / 6800 XT / 6900 XT / 6950 XT** (Navi 21) | gfx1030 | `10.3.0` |
+
+The 7900 XTX has the most community success reports. CachyOS thread has a confirmed working 7800 XT with the same ROCm 7.1.1 pinned stack.
+
+### 🟡 Should work via HSA spoof — not natively supported, spoofs to nearest target
+
+| Card | Real gfx target | Spoofs as | Auto HSA value |
+|------|-----------------|-----------|----------------|
+| **RX 7600 / 7600 XT** (Navi 33) | gfx1102 | gfx1100 | `11.0.0` |
+| **RX 6700 / 6750 XT** (Navi 22) | gfx1031 | gfx1030 | `10.3.0` |
+| **RX 6600 / 6650 XT** (Navi 23) | gfx1032 | gfx1030 | `10.3.0` |
+| **RX 6500 XT / 6400** (Navi 24) | gfx1034 | gfx1030 | `10.3.0` |
+
+**Caveat**: RX 6700 XT has been a problem child historically (see [Arch BBS#284316](https://bbs.archlinux.org/viewtopic.php?id=284316) — one user gave up and switched to NVIDIA). Spoofing trades correctness for not-quite-optimal codegen; some effects may fall back to CPU.
+
+### 🟢 iGPUs
+
+| Chip | gfx target | Notes |
+|------|-----------|-------|
+| Ryzen 7 8000 / 9000 (Phoenix/Hawk Point/Strix) | RDNA3.5 (gfx1150-ish) | CachyOS thread had a 760M (gfx1103) hit the same ROCm 7.2 bug; same downgrade fixes it. |
+| Strix Halo | gfx1151 | Confirmed working via Distrobox per Framework Community Forum. |
+
+### 🔴 Will NOT work — ROCm 7.x dropped support before this script's pinned baseline
+
+- **RX 5000 series** (RDNA1, gfx101x)
+- **Vega** (gfx9)
+- **Polaris** (RX 580 etc.) — only Mesa rusticl path, this script isn't tuned for that
+- **Pre-Polaris GCN**
+
+### What "should work" actually means
+
+For tiers 🟢 and 🟡: the **install path is fully baked in** — same package list, RPATH, audio fixes, and launcher env vars (HSA value auto-matched). What might differ between cards:
+
+- **First-launch latency** — Color page can take 60s+ while shaders compile
+- **Performance ceiling** — spoofed cards (gfx1102, gfx103x) trade correctness for slightly suboptimal codegen
+- **Specific features** — Neural Engine, Fairlight noise reduction may fall back to CPU on some cards
+
+### Sharing the script with someone on a different AMD card
+
+What they need:
+1. Run `~/Downloads/install-davinci-resolve.sh` — auto-detects everything
+2. If launch fails, `verify_opencl()` at the end of the script tells them what's wrong
+3. This notes file has all the diagnostic commands
+
+The one thing they'd need that you don't: the **DaVinci Resolve ZIP in `~/Downloads`** (Blackmagic gates it behind a registration form, no direct link).
+
+## Quick reference: HSA override values
+
+For copy/paste if hand-editing the launcher:
+
+| Card family | gfx target | HSA_OVERRIDE_GFX_VERSION |
+|-------------|-----------|--------------------------|
+| RX 9070 / 9070 XT (Navi 48) | gfx1201 | 12.0.1 |
+| RX 9060 / 9060 XT (Navi 44) | gfx1200 | 12.0.0 |
+| RX 7700 / 7800 (Navi 32) | gfx1101 | 11.0.1 |
+| RX 7900 (Navi 31) | gfx1100 | 11.0.0 |
+| RX 7600 (Navi 33) | gfx1102 | 11.0.0 (spoof) |
+| RX 6800 / 6900 (Navi 21) | gfx1030 | 10.3.0 |
+| RX 6600 / 6700 (Navi 22-24) | gfx1031/1032/1034 | 10.3.0 (spoof) |
+
+## Sources / further reading
+
+- [ROCm/ROCm#5982 — 7.2 OpenCL Breaks Davinci Resolve](https://github.com/ROCm/ROCm/issues/5982)
+- [CachyOS — Davinci Resolve + AMD ROCM fails without downgrade](https://discuss.cachyos.org/t/davinci-resolve-amd-rocm-fails-without-downgrade/28036)
+- [CachyOS — Davinci Resolve + AMD GPU FAQ](https://discuss.cachyos.org/t/davinci-resolve-amd-gpu/28038)
+- [NixOS#481483 — Resolve 20.3.1 OpenCL unusable on RDNA 4](https://github.com/NixOS/nixpkgs/issues/481483)
+- [DaVinci Resolve — ArchWiki](https://wiki.archlinux.org/title/DaVinci_Resolve)
+- [Sheridan Computers — libc++ rollback fix (Oct 2025)](https://sheridancomputers.com/blog/view/videos/fix-davinci-resolve-crashing-on-arch-linux-after-system-update-october-2025)
+- [Arch Linux Archive (ALA) — historic packages](https://archive.archlinux.org/packages/)
+
+## Things still left as future work
+
+- **Resolve 20.3.x stable** — currently on 21.0 beta. Stable might handle the GPU stack differently.
+- **Distrobox + Debian 13** path — community-confirmed working on Strix Halo (gfx1151). Would isolate Resolve from the host's library churn entirely. Useful as a fallback.
+- **libc++ ABI break** — Resolve's bundled libc++ vs Arch's system libc++ has bitten the community before (Oct 2025). When Arch jumps libc++ major versions, Resolve may segfault on launch. Sheridan Computers documented the rollback approach.
+
+## Quick sanity checks (paste into terminal anytime)
+
+```bash
+# Is Resolve install intact?
+test -x /opt/resolve/bin/resolve && echo "Resolve binary OK" || echo "MISSING"
+
+# Is the OpenCL stack the working version?
+pacman -Q rocm-core rocm-opencl-runtime comgr spirv-llvm-translator | grep -E "7\.1\.1|21\.1\.3" | wc -l
+# expect output: 4
+
+# Is the IgnorePkg pin in place?
+grep -q "^IgnorePkg.*rocm-core" /etc/pacman.conf && echo "PINNED" || echo "NOT PINNED"
+
+# Does clinfo see the GPU?
+clinfo -l | grep -i gfx1200
+
+# Does the launcher have the env vars?
+grep -E "HSA_OVERRIDE|ROCR_VISIBLE|DRI_PRIME|MESA_VK" ~/.local/bin/davinci-resolve
+# DRI_PRIME line MUST be the explicit PCI tag form (pci-0000_BB_DD_F),
+# NEVER `=1`. If you see `=1`, fix it before launching:
+# amd_bus=$(lspci -nn | grep -iE 'AMD.*Radeon|Navi' | head -1 | cut -d' ' -f1)
+# sed -i "s|^export DRI_PRIME=.*|export DRI_PRIME=pci-0000_${amd_bus//[:.]/_}|" ~/.local/bin/davinci-resolve
+```
diff --git a/README.md b/README.md
index 9ca6238..507f83a 100644
--- a/README.md
+++ b/README.md
@@ -8,195 +8,154 @@
-Install [DaVinci Resolve](https://www.blackmagicdesign.com/products/davinciresolve) on [Omarchy](https://omarchy.com) (Arch Linux + Hyprland) with AMD GPU support, including the new RX 9000 series (RDNA 4).
+Install [DaVinci Resolve](https://www.blackmagicdesign.com/products/davinciresolve) on [Omarchy](https://omarchy.com) (Arch Linux + Hyprland) on AMD GPUs — RDNA 2, RDNA 3, and the new RDNA 4 cards (RX 9060 / 9070 / 9080).
-Features a pre-installation system scanner that detects your GPU, drivers, OpenCL stack, display server, and audio — then builds a tailored package list for your exact setup.
+The script does a **manual install to `/opt/resolve`** (no AUR PKGBUILD), pins **ROCm 7.1.1** from the Arch Linux Archive (current 7.2.x is broken with Resolve), patches every ELF's RPATH, fixes audio (DeckLink → ALSA + snd-aloop + PipeWire bridge), and writes a launcher with the right `HSA_OVERRIDE` / `DRI_PRIME` / `MESA_VK_DEVICE_SELECT` env vars baked in.
+
+For the full design rationale, root-cause analysis, and recovery procedures see **[NOTES.md](NOTES.md)**.
## Requirements
- **OS**: [Omarchy](https://omarchy.com) (Arch Linux) or any Arch-based distro
-- **GPU**: AMD (RDNA 1 through RDNA 4, including RX 9070/9080)
-- **AUR Helper**: yay or paru
-- **Compositor**: Hyprland (optional, but script adds window rules if detected)
+- **GPU**: AMD RDNA 2 / 3 / 4 (see [GPU support](#gpu-support) below)
+- **Compositor**: Hyprland (optional — script adds window rules if detected)
+- **DaVinci Resolve ZIP** in `~/Downloads/` — Blackmagic gates this behind a registration form, no direct link
## Quick Start
```bash
+# 1. Download DaVinci Resolve from blackmagicdesign.com into ~/Downloads/
+# 2. Clone and run:
git clone https://git.no-signal.uk/nosignal/DaVinci-Resolve-AMD-Omarchy.git
cd DaVinci-Resolve-AMD-Omarchy
chmod +x install-davinci-resolve.sh
./install-davinci-resolve.sh
```
-The script will scan your system, show what it found, and ask before making any changes.
+The script scans your system, shows what it found, asks before making changes, and is idempotent — safe to re-run any time.
-## What It Does
+## Why ROCm 7.1.1 (and not the current 7.2.x)
-### 1. System Scan
+ROCm 7.2.x's OpenCL stack breaks DaVinci Resolve on **every** AMD GPU — `clCreateContext` either fails outright or hangs on the Color page. ROCm 7.1.1 is the last known-good release.
-Before installing anything, the script scans your system to detect:
+The script downloads 7.1.1 from the [Arch Linux Archive](https://archive.archlinux.org/packages/), installs via `pacman -U`, and adds an `IgnorePkg` line to `/etc/pacman.conf` so `pacman -Syu` won't quietly upgrade you back into the broken stack.
-| Component | What It Checks |
-|-----------|---------------|
-| **Kernel** | Version, RDNA 4 compatibility (needs 6.12+) |
-| **GPU(s)** | Vendor, model, RDNA generation, discrete vs integrated |
-| **Hybrid GPU** | Intel/AMD iGPU + discrete GPU detection, PRIME offload support |
-| **Mesa** | Version, OpenGL renderer, Vulkan availability |
-| **OpenCL** | Installed provider, whether AMD platform is actually working |
-| **Audio** | PipeWire or PulseAudio detection |
-| **Display** | Wayland/X11, compositor (Hyprland, Sway, GNOME, KDE) |
-| **Resolve** | Existing installation detection |
-| **Disk space** | Free space on root and home partitions |
+References:
+- [ROCm/ROCm#5982](https://github.com/ROCm/ROCm/issues/5982) — upstream issue, still open
+- [CachyOS thread](https://discuss.cachyos.org/t/davinci-resolve-amd-rocm-fails-without-downgrade/28036) — community recipe
+- [NixOS#481483](https://github.com/NixOS/nixpkgs/issues/481483) — RDNA4-specific report
-### 2. Smart Package Selection
+When ROCm 7.3+ ships and is verified working, the pin can be lifted — see NOTES.md.
-Based on the scan, it builds a package list that:
-- Skips packages already installed
-- Selects the right OpenCL provider for your GPU
-- Removes conflicting packages (e.g. rusticl breaks ROCm)
-- Adds hybrid GPU support if needed
+## What it does
-### 3. OpenCL Provider
+1. **System scan** — kernel, GPU(s) with gfx target + PCI bus address, audio stack, display server, existing Resolve install
+2. **ROCm 7.1.1 pinned install** — downloads from Arch Linux Archive, `pacman -U`, adds `IgnorePkg` to `/etc/pacman.conf`. Aborts on partial-downgrade failure (won't silently leave you on a broken stack)
+3. **Manual Resolve install** — `unzip` → `.run` AppImage → `--appimage-extract` → `rsync` to `/opt/resolve` → `patchelf --set-rpath` every ELF
+4. **glib-family symlink swap** — replaces all five bundled glib libs (`libglib-2.0`, `libgio-2.0`, `libgmodule-2.0`, `libgobject-2.0`, `libgthread-2.0`) with system symlinks. Bundled `libc++` / `libc++abi` are deliberately **kept** (Resolve was compiled against specific ABI versions; replacing them crashes on launch)
+5. **Audio fixes** — DeckLink → ALSA backend, snd-aloop kernel module, PipeWire loopback bridge, wireplumber rule keeping aloop off the default-sink rotation
+6. **Hyprland window rules** — v3 syntax (not deprecated `windowrulev2`), cosmetic-only on the modal dialogs to avoid the trapped-cursor problem
+7. **Launcher** at `~/.local/bin/davinci-resolve` with `HSA_OVERRIDE_GFX_VERSION`, `ROCR_VISIBLE_DEVICES`, `DRI_PRIME=pci-` (explicit tag, not `=1` — see below), and `MESA_VK_DEVICE_SELECT` baked in
+8. **Stale-config wipe** — clears `~/.local/share/DaVinciResolve/{configs,logs}` if it sees a known crash marker, and unconditionally on fresh installs
-Two options (configurable in the script):
+## Hybrid GPU note (Intel iGPU + AMD dGPU)
-| Provider | Source | Best For |
-|----------|--------|----------|
-| `opencl-amd` (default) | AUR | Recommended by Arch Wiki for Resolve |
-| `rocm-full` | Official repos | Full ROCm/HIP stack, better RDNA 4 support |
+On hybrid laptops where the monitor is wired to the AMD discrete card, Mesa already defaults OpenGL to the AMD card. Setting `DRI_PRIME=1` in this scenario actually flips OpenGL to the **Intel** iGPU — Resolve then has OpenGL on Intel and OpenCL on AMD, CL/GL interop fails, and Resolve hangs on the Color page.
-### 4. Installs DaVinci Resolve
+The launcher uses the **explicit PCI tag form** (`DRI_PRIME=pci-0000_BB_DD_F`) derived from the AMD card's `lspci` ID. `switcherooctl` is **not** used — it internally sets `DRI_PRIME=1` and inherits the same flip bug.
-Installs via the AUR package (`davinci-resolve` or `davinci-resolve-studio`).
+## GPU support
-### 5. Applies Compatibility Fixes
+The script auto-detects the gfx target and applies the right HSA override unattended.
-| Fix | Method | Why |
-|-----|--------|-----|
-| **GLib conflict** | patchelf (davincibox-style) | Cleaner than LD_PRELOAD, survives updates |
-| **OpenCL decoders** | Disable BlackmagicRaw OpenCL | Prevents crashes with AMD OpenCL |
-| **Rusticl removal** | Removes conflicting packages | Mesa's rusticl breaks ROCm OpenCL |
-| **XWayland wrapper** | Custom launcher script | Resolve doesn't support native Wayland |
-| **RDNA 4 env vars** | HSA_OVERRIDE_GFX_VERSION | Tells ROCm how to talk to gfx1201 GPUs |
+### Confirmed working (tested directly)
-### 6. Creates Launcher
+| Card | gfx target | HSA value |
+|------|-----------|-----------|
+| **RX 9060 / 9060 XT** (Navi 44) | gfx1200 | `12.0.0` |
-A wrapper script at `~/.local/bin/davinci-resolve` that:
-- Forces XWayland mode (`QT_QPA_PLATFORM=xcb`)
-- Sets ROCm/OpenCL environment variables
-- Handles DRI_PRIME for hybrid GPU setups
-- Sets RDNA 4 GFX version override if needed
+### Should work — natively supported by ROCm 7.1.1
-### 7. Configures Hyprland
+| Card | gfx target | HSA value |
+|------|-----------|-----------|
+| **RX 9070 / 9070 XT** (Navi 48) | gfx1201 | `12.0.1` |
+| **RX 7900 / 7900 XT / 7900 XTX** (Navi 31) | gfx1100 | `11.0.0` |
+| **RX 7700 XT / 7800 XT** (Navi 32) | gfx1101 | `11.0.1` |
+| **RX 6800 / 6800 XT / 6900 XT / 6950 XT** (Navi 21) | gfx1030 | `10.3.0` |
-Adds window rules to `hyprland.conf` for Resolve's floating dialogs (file pickers, render settings, etc.) so they behave correctly under Hyprland.
+### Should work via HSA spoof — not natively supported, spoofed to nearest target
-### 8. Bonus Tools
+| Card | Real gfx | Spoofs as | HSA value |
+|------|----------|-----------|-----------|
+| **RX 7600 / 7600 XT** (Navi 33) | gfx1102 | gfx1100 | `11.0.0` |
+| **RX 6700 / 6750 XT** (Navi 22) | gfx1031 | gfx1030 | `10.3.0` |
+| **RX 6600 / 6650 XT** (Navi 23) | gfx1032 | gfx1030 | `10.3.0` |
+| **RX 6500 XT / 6400** (Navi 24) | gfx1034 | gfx1030 | `10.3.0` |
-- **resolve-convert** — Converts MP4/MKV to DNxHR format (DaVinci Resolve Free on Linux doesn't support H.264/H.265)
-- **davinci-resolve-checker** — Community diagnostic tool for troubleshooting Resolve issues
+### Not supported — ROCm 7.x dropped these before our pinned baseline
-## Supported AMD GPUs
+- **RX 5000 series** (RDNA 1)
+- **Vega**
+- **Polaris and earlier** (rusticl-only path, this script isn't tuned for it)
-| Generation | GPUs | Notes |
-|-----------|------|-------|
-| **RDNA 4** | RX 9070, 9080 | Needs kernel 6.12+, Mesa 25+ |
-| **RDNA 3** | RX 7600–7900 | Full support |
-| **RDNA 2** | RX 6400–6950 | Full support |
-| **RDNA 1** | RX 5500–5700 | Full support |
-| **Vega** | Vega 56/64 | Supported |
-| **GCN** | Older cards | May work, not tested |
+## Free-version codec limitation
-## Hybrid GPU Support
-
-The script detects and handles these configurations:
-
-- **Intel iGPU + AMD dGPU** — Configures DRI_PRIME for discrete GPU
-- **AMD iGPU + AMD dGPU** — Auto-selects discrete GPU
-- **Intel iGPU + NVIDIA dGPU** — Advises on PRIME render offload
-- **AMD iGPU + NVIDIA dGPU** — Advises on PRIME render offload
-
-## Configuration
-
-### Changing OpenCL Provider
-
-Edit the script and change `OPENCL_PROVIDER`:
+DaVinci Resolve Free on Linux can't decode H.264/H.265. Convert media first:
```bash
-# In install-davinci-resolve.sh:
-OPENCL_PROVIDER="opencl-amd" # AUR package (default)
-OPENCL_PROVIDER="rocm-full" # Official ROCm stack
+resolve-convert video.mp4 # writes video_dnxhr.mov (DNxHR)
```
-### Free Version Codec Limitation
+## Environment variables
-DaVinci Resolve Free on Linux cannot decode H.264/H.265. Convert your media first:
+| Var | Effect |
+|-----|--------|
+| `RESOLVE_NO_ALOOP=1` | Skip the snd-aloop / PipeWire bridge audio setup (use this if you have a real audio interface) |
+
+## Uninstall
+
+The script does **not** track itself with pacman. To remove cleanly:
```bash
-resolve-convert video.mp4
-# Creates video_dnxhr.mov (DNxHR format that Resolve Free supports)
+sudo rm -rf /opt/resolve
+sudo rm -f /usr/share/applications/{DaVinciResolve,blackmagicraw-*}.desktop
+sudo rm -f /usr/lib/udev/rules.d/{99-BlackmagicDevices,99-ResolveKeyboardHID,99-DavinciPanel}.rules
+rm -f ~/.local/bin/davinci-resolve ~/.local/bin/davinci-resolve-rusticl ~/.local/bin/davinci-resolve-igpu
+rm -f ~/.local/bin/resolve-convert ~/.local/bin/davinci-resolve-checker
+
+# Optional — also remove user data (DELETES ALL PROJECTS)
+rm -rf ~/.local/share/DaVinciResolve
+```
+
+To lift the ROCm pin:
+
+```bash
+sudo sed -i '/^IgnorePkg.*rocm-/d' /etc/pacman.conf
+sudo pacman -Syu
```
## Troubleshooting
-### GPU not detected in Resolve
+If first launch fails or Resolve hangs on the Color page, **[NOTES.md](NOTES.md)** has the full recovery playbook — quick sanity checks at the bottom let you verify the OpenCL stack, launcher env vars, and PipeWire bridge in a few lines of paste.
+
+Common quick checks:
```bash
-# Check OpenCL
-clinfo --list
-
-# Check ROCm
-rocminfo
-
-# Run diagnostics
-davinci-resolve-checker
-```
-
-### RDNA 4 specific issues
-
-If Resolve doesn't detect your RX 9070/9080, try adjusting the GFX version in the launcher:
-
-```bash
-# Edit ~/.local/bin/davinci-resolve
-# Change HSA_OVERRIDE_GFX_VERSION value:
-# 11.0.1 (default for gfx1201)
-# 11.0.0 (fallback to gfx1100)
-```
-
-### Resolve crashes on launch
-
-- Check patchelf fix is applied: `patchelf --print-needed /opt/resolve/bin/resolve | grep glib`
-- Re-run the script to reapply fixes
-- Check logs: `~/.local/share/DaVinciResolve/logs/`
-
-### Kernel 6.14/6.15 ROCm issues
-
-Kernels 6.14 and 6.15 have known DKMS issues with ROCm. Consider using kernel 6.12 or 6.13.
-
-## Uninstalling
-
-```bash
-# Remove Resolve (AUR package)
-yay -Rns davinci-resolve
-
-# Remove launcher and tools
-rm -f ~/.local/bin/davinci-resolve
-rm -f ~/.local/bin/resolve-convert
-rm -f ~/.local/bin/davinci-resolve-checker
-rm -rf ~/.local/share/davinci-resolve-checker
-
-# Remove user data (WARNING: deletes all projects)
-rm -rf ~/.local/share/DaVinciResolve
+clinfo -l # should show your AMD gfx target
+pacman -Q rocm-core rocm-opencl-runtime # should show 7.1.1
+grep IgnorePkg /etc/pacman.conf # should pin the rocm packages
+grep -E 'DRI_PRIME|HSA_OVERRIDE' ~/.local/bin/davinci-resolve # DRI_PRIME must be pci-... form, NEVER =1
```
## Credits
-- [Omarchy](https://omarchy.com) - The Arch Linux distribution this was built for
-- [davincibox](https://github.com/zelikos/davincibox) - Patchelf fix technique
-- [Arch Wiki - DaVinci Resolve](https://wiki.archlinux.org/title/DaVinci_Resolve) - Community documentation
-- [Blackmagic Design](https://www.blackmagicdesign.com/) - DaVinci Resolve
-- [davinci-resolve-checker](https://github.com/Ashark/davinci-resolve-checker) - Diagnostic tool
+- [Omarchy](https://omarchy.com) — the Arch + Hyprland distribution this targets
+- [davincibox](https://github.com/zelikos/davincibox) — patchelf RPATH technique
+- [Arch Wiki — DaVinci Resolve](https://wiki.archlinux.org/title/DaVinci_Resolve) — community documentation
+- [Sheridan Computers](https://sheridancomputers.com/blog/view/videos/fix-davinci-resolve-crashing-on-arch-linux-after-system-update-october-2025) — libc++ ABI rollback writeup
+- [Blackmagic Design](https://www.blackmagicdesign.com/) — DaVinci Resolve
+- [davinci-resolve-checker](https://github.com/Ashark/davinci-resolve-checker) — diagnostic tool
## License
-This project is provided as-is for the Omarchy community.
+Provided as-is for the Omarchy community.
diff --git a/install-davinci-resolve.sh b/install-davinci-resolve.sh
index 1d2bdb6..ea6a2f9 100755
--- a/install-davinci-resolve.sh
+++ b/install-davinci-resolve.sh
@@ -1,24 +1,38 @@
#!/bin/bash
# =============================================================================
-# DaVinci Resolve Free - Arch Linux + AMD RX 9000 + Hyprland Install Script
+# DaVinci Resolve Free - Arch Linux + AMD (RDNA2/3/4) + Hyprland Install Script
# =============================================================================
#
-# Version 3.0 - Davincibox-style fixes for better compatibility
-# Validated against Arch Wiki, AUR, davincibox, and community docs (Dec 2025)
+# Version 4.1 - Mirrors the proven NVIDIA-Open install path; only the GPU
+# stack (ROCm vs CUDA) and HSA_OVERRIDE handling differ.
+# 4.1: pinned ROCm 7.1.1 from Arch Linux Archive as default OpenCL provider,
+# because Arch's current ROCm 7.2.x breaks DaVinci Resolve on AMD.
#
-# Features:
-# - Pre-installation system scan to detect configuration
-# - Smart package selection based on existing setup
-# - AMD RX 9000 series (RDNA 4 / gfx1201) GPU support via ROCm
-# - Choice of OpenCL provider: rocm-full (recommended) or opencl-amd (AUR)
-# - Patchelf fix for glib issues (cleaner than LD_PRELOAD)
-# - Disables problematic BlackmagicRaw OpenCL decoders
-# - Removes conflicting OpenCL packages (rusticl breaks ROCm)
-# - Hyprland compatibility (XWayland required)
-# - Hybrid GPU support (Intel/AMD iGPU + discrete GPU)
+# Install method (shared with NVIDIA script):
+# 1. Find the Resolve ZIP in ~/Downloads/
+# 2. unzip ZIP -> .run AppImage -> --appimage-extract -> squashfs-root
+# 3. Replace bundled glib/gio/gmodule with system symlinks (ABI-safe)
+# KEEP vendored libc++/libc++abi (removing breaks Resolve)
+# 4. rsync to /opt/resolve, patchelf --set-rpath every ELF
+# 5. Install desktop entries, icons, udev rules system-wide
+# 6. Apply audio fixes: DeckLink->ALSA, snd-aloop, PipeWire bridge
+# 7. Apply Hyprland window rules and create XWayland launcher
+#
+# AMD-specific bits:
+# - ROCm 7.2 (Arch extra) for OpenCL, with auto-detected HSA_OVERRIDE for
+# RDNA2/3/4 cards that aren't natively in ROCm's supported list
+# - Generation-aware gfx target detection (gfx1030/1100/1101/1102/1200/1201)
+# - switcherooctl integration for hybrid Intel/AMD systems
+# - BlackmagicRaw OpenCL decoder disable (prevents ROCm conflicts)
+#
+# Pacman does NOT track this install. To remove:
+# sudo rm -rf /opt/resolve
+# sudo rm -f /usr/share/applications/{DaVinciResolve,blackmagicraw-*}.desktop
+# sudo rm -f /usr/lib/udev/rules.d/{99-BlackmagicDevices,99-ResolveKeyboardHID,99-DavinciPanel}.rules
#
# Based on techniques from:
+# - The Omarchy NVIDIA-Open Resolve installer (this script is its mirror)
# - https://github.com/zelikos/davincibox
# - https://wiki.archlinux.org/title/DaVinci_Resolve
#
@@ -26,6 +40,9 @@
# chmod +x install-davinci-resolve.sh
# ./install-davinci-resolve.sh
#
+# Env vars:
+# RESOLVE_NO_ALOOP=1 Skip snd-aloop setup (you have a real audio interface)
+#
# =============================================================================
set -e
@@ -52,14 +69,22 @@ scan_item() { echo -e " ${MAGENTA}•${NC} $1: ${BOLD}$2${NC}"; }
# CONFIGURATION OPTIONS
# =============================================================================
-# OpenCL Provider: "opencl-amd" (AUR) or "rocm-full" (official Arch ROCm stack)
-# opencl-amd: Uses AUR package (7.1.1+), includes both ROCm and ORCA - RECOMMENDED
-# rocm-full: Uses official Arch repos (6.4.4+), full ROCm stack with HIP
-#
-# NOTE: Arch Wiki recommends opencl-amd for DaVinci Resolve
-# "DaVinci Resolve seems to need opencl-amd and doesn't work with rocm-opencl-runtime"
-# Change to "rocm-full" if you need HIP support or experience issues
-OPENCL_PROVIDER="opencl-amd"
+# OpenCL Provider:
+# "rocm-pinned-7.1.1" - DEFAULT. ROCm 7.1.1 stack from Arch Linux Archive,
+# pinned in /etc/pacman.conf IgnorePkg. This is the
+# ONLY currently-known-working configuration for
+# DaVinci Resolve on AMD as of May 2026.
+# Confirmed by CachyOS community + this script's
+# own testing on RX 9060 XT (Navi 44, gfx1200).
+# Refs:
+# https://github.com/ROCm/ROCm/issues/5982
+# https://discuss.cachyos.org/t/davinci-resolve-amd-rocm-fails-without-downgrade/28036
+# "rocm-full" - Current Arch repos ROCm 7.2.x. KNOWN BROKEN with
+# DaVinci Resolve - clCreateContext fails or hangs
+# on Color page. Will work again when ROCm 7.3+ ships.
+# "opencl-amd" - AUR opencl-amd 7.2.x. Same ROCm 7.2 ABI bug.
+# KNOWN BROKEN with Resolve currently.
+OPENCL_PROVIDER="rocm-pinned-7.1.1"
# =============================================================================
# SYSTEM SCAN VARIABLES (populated during scan)
@@ -86,8 +111,12 @@ SCAN_GPU_MODELS=()
SCAN_GPU_TYPES=()
SCAN_GPU_PCI_IDS=()
SCAN_GPU_RDNA_VERSIONS=()
+SCAN_GPU_GFX_TARGETS=() # Per-GPU gfx target (e.g. gfx1030, gfx1102, gfx1200)
+SCAN_GPU_HSA_OVERRIDES=() # Per-GPU recommended HSA_OVERRIDE_GFX_VERSION ("" if natively supported)
SCAN_GPU_DRIVERS_LOADED=()
SCAN_PRIMARY_GPU_INDEX=0
+SCAN_HSA_OVERRIDE_VALUE="" # Set from primary GPU after scan
+SCAN_GFX_TARGET="" # Set from primary GPU after scan
# Hybrid GPU flags
SCAN_HAS_IGPU=false
@@ -156,7 +185,7 @@ scan_gpu() {
SCAN_GPU_MODELS=() # Array of models
SCAN_GPU_TYPES=() # "integrated" or "discrete"
SCAN_GPU_PCI_IDS=() # PCI bus IDs
-
+
# Flags for GPU types present
SCAN_HAS_IGPU=false
SCAN_HAS_DGPU=false
@@ -165,28 +194,44 @@ scan_gpu() {
SCAN_HAS_AMD_IGPU=false
SCAN_HAS_INTEL_IGPU=false
SCAN_IS_HYBRID=false
-
+
# Primary GPU for DaVinci Resolve (discrete preferred)
SCAN_PRIMARY_GPU_INDEX=0
-
+
if ! command -v lspci &>/dev/null; then
return
fi
-
+
# Get all GPUs
while IFS= read -r gpu_line; do
[[ -z "$gpu_line" ]] && continue
-
+
local pci_id=$(echo "$gpu_line" | cut -d' ' -f1)
local gpu_info=$(echo "$gpu_line" | sed 's/^[^ ]* //' | sed 's/.*: //')
local vendor=""
local gpu_type="discrete" # Default assumption
local rdna_ver=""
-
- # Detect vendor and type
- if echo "$gpu_line" | grep -qi "AMD\|ATI\|Radeon"; then
+
+ # Detect vendor and type.
+ # Order matters: check Intel/NVIDIA first because "ATI" matches
+ # "Corpor[ATI]on" in Intel/NVIDIA lspci lines case-insensitively.
+ if echo "$gpu_line" | grep -qi "Intel"; then
+ vendor="Intel"
+ gpu_type="integrated"
+ SCAN_HAS_IGPU=true
+ SCAN_HAS_INTEL_IGPU=true
+ rdna_ver="N/A"
+
+ elif echo "$gpu_line" | grep -qi "NVIDIA"; then
+ vendor="NVIDIA"
+ gpu_type="discrete"
+ SCAN_HAS_DGPU=true
+ SCAN_HAS_NVIDIA_DGPU=true
+ rdna_ver="N/A"
+
+ elif echo "$gpu_line" | grep -qiE '\bAMD\b|\bATI\b|Radeon'; then
vendor="AMD"
-
+
# Check if integrated (APU) - common identifiers
if echo "$gpu_line" | grep -qiE "Radeon.*(Graphics|Vega|RX Vega|Renoir|Cezanne|Barcelo|Rembrandt|Phoenix|Hawk|Strix Point)|AMD.*Ryzen.*Radeon|Integrated"; then
gpu_type="integrated"
@@ -197,7 +242,7 @@ scan_gpu() {
SCAN_HAS_DGPU=true
SCAN_HAS_AMD_DGPU=true
fi
-
+
# Detect RDNA generation
if echo "$gpu_line" | grep -qiE "9070|9080|Navi 4|gfx1201"; then
rdna_ver="RDNA4"
@@ -217,45 +262,70 @@ scan_gpu() {
else
rdna_ver="Pre-RDNA/GCN"
fi
-
- elif echo "$gpu_line" | grep -qi "NVIDIA"; then
- vendor="NVIDIA"
- gpu_type="discrete"
- SCAN_HAS_DGPU=true
- SCAN_HAS_NVIDIA_DGPU=true
- rdna_ver="N/A"
-
- elif echo "$gpu_line" | grep -qi "Intel"; then
- vendor="Intel"
- gpu_type="integrated"
- SCAN_HAS_IGPU=true
- SCAN_HAS_INTEL_IGPU=true
- rdna_ver="N/A"
+
+ # Detect gfx target and required HSA_OVERRIDE_GFX_VERSION.
+ # ROCm 7.2 officially supports: gfx1030, gfx1100, gfx1101, gfx1200, gfx1201.
+ # Other RDNA2/3 silicon needs HSA_OVERRIDE to spoof as the nearest supported target.
+ local gfx_target=""
+ local hsa_override=""
+
+ # RDNA4 - all natively supported
+ if echo "$gpu_line" | grep -qiE "Navi 48|9070|9080|gfx1201"; then
+ gfx_target="gfx1201"
+ elif echo "$gpu_line" | grep -qiE "Navi 44|RX 90[6-9][0-9]|gfx1200"; then
+ gfx_target="gfx1200"
+
+ # RDNA3
+ elif echo "$gpu_line" | grep -qiE "Navi 31|RX 79[0-9]{2}|gfx1100"; then
+ gfx_target="gfx1100"
+ elif echo "$gpu_line" | grep -qiE "Navi 32|RX 7[78][0-9]{2}|gfx1101"; then
+ gfx_target="gfx1101"
+ elif echo "$gpu_line" | grep -qiE "Navi 33|RX 76[0-9]{2}|gfx1102"; then
+ gfx_target="gfx1102"
+ hsa_override="11.0.0" # gfx1102 not natively supported, spoof as gfx1100
+
+ # RDNA2
+ elif echo "$gpu_line" | grep -qiE "Navi 21|RX 6[89][0-9]{2}|gfx1030"; then
+ gfx_target="gfx1030"
+ elif echo "$gpu_line" | grep -qiE "Navi 22|RX 67[0-9]{2}|gfx1031"; then
+ gfx_target="gfx1031"
+ hsa_override="10.3.0" # spoof as gfx1030
+ elif echo "$gpu_line" | grep -qiE "Navi 23|RX 66[0-9]{2}|gfx1032"; then
+ gfx_target="gfx1032"
+ hsa_override="10.3.0"
+ elif echo "$gpu_line" | grep -qiE "Navi 24|RX 6[45][0-9]{2}|gfx1034"; then
+ gfx_target="gfx1034"
+ hsa_override="10.3.0"
+ fi
fi
-
+
# Store GPU info
SCAN_GPUS+=("$gpu_info")
SCAN_GPU_VENDORS+=("$vendor")
SCAN_GPU_MODELS+=("$gpu_info")
SCAN_GPU_TYPES+=("$gpu_type")
SCAN_GPU_PCI_IDS+=("$pci_id")
-
- # Store RDNA version for AMD GPUs
+
+ # Store RDNA version, gfx target, and HSA override for AMD GPUs
if [[ "$vendor" == "AMD" ]]; then
SCAN_GPU_RDNA_VERSIONS+=("$rdna_ver")
+ SCAN_GPU_GFX_TARGETS+=("$gfx_target")
+ SCAN_GPU_HSA_OVERRIDES+=("$hsa_override")
else
SCAN_GPU_RDNA_VERSIONS+=("")
+ SCAN_GPU_GFX_TARGETS+=("")
+ SCAN_GPU_HSA_OVERRIDES+=("")
fi
-
+
SCAN_GPU_COUNT=$((SCAN_GPU_COUNT + 1))
-
+
done < <(lspci 2>/dev/null | grep -iE "VGA|3D|Display")
-
+
# Detect hybrid graphics
if [[ "$SCAN_HAS_IGPU" == true && "$SCAN_HAS_DGPU" == true ]]; then
SCAN_IS_HYBRID=true
fi
-
+
# Select primary GPU for DaVinci Resolve (prefer discrete AMD, then discrete NVIDIA, then any AMD)
for i in "${!SCAN_GPU_VENDORS[@]}"; do
if [[ "${SCAN_GPU_VENDORS[$i]}" == "AMD" && "${SCAN_GPU_TYPES[$i]}" == "discrete" ]]; then
@@ -263,7 +333,7 @@ scan_gpu() {
break
fi
done
-
+
# If no discrete AMD, check for discrete NVIDIA
if [[ ${#SCAN_GPU_TYPES[@]} -gt 0 && "${SCAN_GPU_TYPES[$SCAN_PRIMARY_GPU_INDEX]}" != "discrete" ]]; then
for i in "${!SCAN_GPU_VENDORS[@]}"; do
@@ -273,14 +343,16 @@ scan_gpu() {
fi
done
fi
-
+
# Set legacy variables for compatibility (using primary GPU)
if [[ $SCAN_GPU_COUNT -gt 0 ]]; then
SCAN_GPU_VENDOR="${SCAN_GPU_VENDORS[$SCAN_PRIMARY_GPU_INDEX]}"
SCAN_GPU_MODEL="${SCAN_GPU_MODELS[$SCAN_PRIMARY_GPU_INDEX]}"
SCAN_GPU_RDNA_VERSION="${SCAN_GPU_RDNA_VERSIONS[$SCAN_PRIMARY_GPU_INDEX]}"
+ SCAN_GFX_TARGET="${SCAN_GPU_GFX_TARGETS[$SCAN_PRIMARY_GPU_INDEX]}"
+ SCAN_HSA_OVERRIDE_VALUE="${SCAN_GPU_HSA_OVERRIDES[$SCAN_PRIMARY_GPU_INDEX]}"
fi
-
+
# Check loaded kernel drivers
SCAN_GPU_DRIVERS_LOADED=()
if lsmod 2>/dev/null | grep -q "^amdgpu"; then
@@ -298,7 +370,7 @@ scan_gpu() {
if lsmod 2>/dev/null | grep -q "^radeon"; then
SCAN_GPU_DRIVERS_LOADED+=("radeon")
fi
-
+
# Detect DRI_PRIME / PRIME render offload status
SCAN_PRIME_AVAILABLE=false
if [[ "$SCAN_IS_HYBRID" == true ]]; then
@@ -316,12 +388,12 @@ scan_mesa() {
if command -v glxinfo &>/dev/null; then
SCAN_MESA_VERSION=$(glxinfo 2>/dev/null | grep "OpenGL version" | grep -oP "Mesa \K[0-9]+\.[0-9]+(\.[0-9]+)?" || echo "")
SCAN_OPENGL_RENDERER=$(glxinfo 2>/dev/null | grep "OpenGL renderer" | sed 's/OpenGL renderer string: //' || echo "")
-
+
if [[ -n "$SCAN_MESA_VERSION" ]]; then
SCAN_MESA_MAJOR=$(echo "$SCAN_MESA_VERSION" | cut -d'.' -f1)
fi
fi
-
+
# Check Vulkan
if command -v vulkaninfo &>/dev/null && vulkaninfo --summary &>/dev/null; then
SCAN_VULKAN_AVAILABLE=true
@@ -374,7 +446,7 @@ scan_audio() {
SCAN_PULSEAUDIO_INSTALLED=true
fi
fi
-
+
# Double-check with package detection
if pacman -Qq pipewire &>/dev/null; then
SCAN_PIPEWIRE_INSTALLED=true
@@ -382,7 +454,7 @@ scan_audio() {
if pacman -Qq pulseaudio &>/dev/null; then
SCAN_PULSEAUDIO_INSTALLED=true
fi
-
+
# If we couldn't detect from pactl, use package info
if [[ -z "$SCAN_AUDIO_SERVER" ]]; then
if [[ "$SCAN_PIPEWIRE_INSTALLED" == true ]]; then
@@ -407,7 +479,7 @@ scan_display() {
else
SCAN_DISPLAY_SERVER="None/TTY"
fi
-
+
# Detect compositor
if [[ -n "$HYPRLAND_INSTANCE_SIGNATURE" ]]; then
SCAN_COMPOSITOR="Hyprland"
@@ -424,7 +496,7 @@ scan_display() {
else
SCAN_COMPOSITOR="Unknown"
fi
-
+
# Check if Hyprland is installed
if pacman -Qq hyprland &>/dev/null || command -v Hyprland &>/dev/null; then
SCAN_HYPRLAND_INSTALLED=true
@@ -436,13 +508,13 @@ scan_resolve() {
if [[ -d "/opt/resolve" ]] || [[ -f "/opt/resolve/bin/resolve" ]]; then
SCAN_RESOLVE_INSTALLED=true
SCAN_RESOLVE_PATH="/opt/resolve"
-
+
# Try to get version
if [[ -f "/opt/resolve/docs/License.txt" ]]; then
SCAN_RESOLVE_VERSION=$(grep -oP "DaVinci Resolve \K[0-9]+\.[0-9]+(\.[0-9]+)?" /opt/resolve/docs/License.txt 2>/dev/null | head -1 || echo "Unknown")
fi
fi
-
+
# Also check via pacman
if pacman -Qq davinci-resolve &>/dev/null || pacman -Qq davinci-resolve-studio &>/dev/null; then
SCAN_RESOLVE_INSTALLED=true
@@ -484,50 +556,50 @@ is_pkg_installed() {
run_system_scan() {
header "System Scan"
-
+
echo -e "${BOLD}Scanning your system to optimize installation...${NC}\n"
-
+
# Run all scans
echo -n " Scanning kernel... "
scan_kernel
echo -e "${GREEN}done${NC}"
-
+
echo -n " Scanning GPU... "
scan_gpu
echo -e "${GREEN}done${NC}"
-
+
echo -n " Scanning graphics stack... "
scan_mesa
echo -e "${GREEN}done${NC}"
-
+
echo -n " Scanning OpenCL... "
scan_opencl
echo -e "${GREEN}done${NC}"
-
+
echo -n " Scanning audio... "
scan_audio
echo -e "${GREEN}done${NC}"
-
+
echo -n " Scanning display... "
scan_display
echo -e "${GREEN}done${NC}"
-
+
echo -n " Scanning for DaVinci Resolve... "
scan_resolve
echo -e "${GREEN}done${NC}"
-
+
echo -n " Scanning AUR helpers... "
scan_aur_helper
echo -e "${GREEN}done${NC}"
-
+
echo -n " Scanning disk space... "
scan_disk_space
echo -e "${GREEN}done${NC}"
-
+
echo -n " Scanning installed packages... "
scan_installed_packages
echo -e "${GREEN}done${NC}"
-
+
echo ""
}
@@ -537,14 +609,14 @@ run_system_scan() {
display_scan_results() {
header "System Configuration Detected"
-
+
echo -e "${BOLD}System:${NC}"
scan_item "Kernel" "$SCAN_KERNEL_VERSION"
scan_item "Architecture" "$SCAN_ARCH"
-
+
echo ""
echo -e "${BOLD}GPU(s) Detected: ${SCAN_GPU_COUNT}${NC}"
-
+
if [[ $SCAN_GPU_COUNT -eq 0 ]]; then
scan_item "GPU" "None detected"
else
@@ -552,25 +624,35 @@ display_scan_results() {
local gpu_label="GPU $((i+1))"
local gpu_type_label="${SCAN_GPU_TYPES[$i]}"
local vendor="${SCAN_GPU_VENDORS[$i]}"
-
+
# Mark primary GPU
local primary_marker=""
if [[ $i -eq $SCAN_PRIMARY_GPU_INDEX ]]; then
primary_marker=" ${GREEN}← PRIMARY${NC}"
fi
-
+
echo ""
echo -e " ${BOLD}$gpu_label ($gpu_type_label):${NC}$primary_marker"
echo -e " Vendor: ${SCAN_GPU_VENDORS[$i]}"
echo -e " Model: ${SCAN_GPU_MODELS[$i]}"
-
+
if [[ "$vendor" == "AMD" && -n "${SCAN_GPU_RDNA_VERSIONS[$i]}" ]]; then
echo -e " Gen: ${SCAN_GPU_RDNA_VERSIONS[$i]}"
fi
-
+
+ if [[ "$vendor" == "AMD" && -n "${SCAN_GPU_GFX_TARGETS[$i]}" ]]; then
+ local override_note=""
+ if [[ -n "${SCAN_GPU_HSA_OVERRIDES[$i]}" ]]; then
+ override_note=" ${YELLOW}(needs HSA_OVERRIDE_GFX_VERSION=${SCAN_GPU_HSA_OVERRIDES[$i]})${NC}"
+ else
+ override_note=" ${GREEN}(natively supported)${NC}"
+ fi
+ echo -e " GFX: ${SCAN_GPU_GFX_TARGETS[$i]}$override_note"
+ fi
+
echo -e " PCI: ${SCAN_GPU_PCI_IDS[$i]}"
done
-
+
echo ""
if [[ "$SCAN_IS_HYBRID" == true ]]; then
echo -e " ${YELLOW}⚡ Hybrid Graphics Detected${NC}"
@@ -578,18 +660,18 @@ display_scan_results() {
echo -e " DRI_PRIME offloading available"
fi
fi
-
+
if [[ ${#SCAN_GPU_DRIVERS_LOADED[@]} -gt 0 ]]; then
echo -e " Loaded drivers: ${SCAN_GPU_DRIVERS_LOADED[*]}"
fi
fi
-
+
echo ""
echo -e "${BOLD}Graphics Stack:${NC}"
scan_item "Mesa" "${SCAN_MESA_VERSION:-Not detected}"
scan_item "OpenGL Renderer" "${SCAN_OPENGL_RENDERER:-Not detected}"
scan_item "Vulkan" "$( [[ "$SCAN_VULKAN_AVAILABLE" == true ]] && echo "Available" || echo "Not available" )"
-
+
echo ""
echo -e "${BOLD}OpenCL:${NC}"
if [[ "$SCAN_OPENCL_INSTALLED" == true ]]; then
@@ -598,17 +680,17 @@ display_scan_results() {
else
scan_item "Status" "Not installed"
fi
-
+
echo ""
echo -e "${BOLD}Audio:${NC}"
scan_item "Server" "$SCAN_AUDIO_SERVER"
-
+
echo ""
echo -e "${BOLD}Display:${NC}"
scan_item "Server" "$SCAN_DISPLAY_SERVER"
scan_item "Compositor" "$SCAN_COMPOSITOR"
scan_item "Hyprland" "$( [[ "$SCAN_HYPRLAND_INSTALLED" == true ]] && echo "Installed" || echo "Not installed" )"
-
+
echo ""
echo -e "${BOLD}DaVinci Resolve:${NC}"
if [[ "$SCAN_RESOLVE_INSTALLED" == true ]]; then
@@ -618,16 +700,16 @@ display_scan_results() {
else
scan_item "Status" "Not installed"
fi
-
+
echo ""
echo -e "${BOLD}Package Management:${NC}"
scan_item "AUR Helper" "${SCAN_AUR_HELPER:-None detected}"
-
+
echo ""
echo -e "${BOLD}Disk Space:${NC}"
scan_item "Root partition" "${SCAN_ROOT_FREE_GB}GB free"
scan_item "Home partition" "${SCAN_HOME_FREE_GB}GB free"
-
+
echo ""
}
@@ -637,97 +719,103 @@ display_scan_results() {
analyze_scan_results() {
header "Analysis & Recommendations"
-
+
local issues=0
local warnings=0
-
+
# Check kernel compatibility
if [[ $SCAN_KERNEL_MAJOR -lt 6 ]] || [[ $SCAN_KERNEL_MAJOR -eq 6 && $SCAN_KERNEL_MINOR -lt 12 ]]; then
if [[ "$SCAN_IS_RDNA4" == true ]]; then
echo -e "${RED}[ISSUE]${NC} Kernel $SCAN_KERNEL_VERSION is too old for RDNA 4. Need 6.12+."
- ((issues++))
+ issues=$((issues+1))
fi
fi
-
+
if [[ $SCAN_KERNEL_MAJOR -eq 6 && ($SCAN_KERNEL_MINOR -eq 14 || $SCAN_KERNEL_MINOR -eq 15) ]]; then
echo -e "${YELLOW}[WARNING]${NC} Kernel 6.14/6.15 has ROCm DKMS issues. Consider 6.12 or 6.13."
- ((warnings++))
+ warnings=$((warnings+1))
fi
-
+
+ # Kernel 7.x is bleeding edge - ROCm DKMS may not yet support it
+ if [[ $SCAN_KERNEL_MAJOR -ge 7 ]]; then
+ echo -e "${YELLOW}[WARNING]${NC} Kernel $SCAN_KERNEL_VERSION is very new. ROCm DKMS may not support it yet."
+ warnings=$((warnings+1))
+ fi
+
# =========================================================================
# HYBRID GPU HANDLING
# =========================================================================
-
+
if [[ "$SCAN_IS_HYBRID" == true ]]; then
echo -e "${CYAN}[HYBRID GPU]${NC} Multiple GPUs detected - special configuration needed."
-
+
# AMD iGPU + AMD dGPU
if [[ "$SCAN_HAS_AMD_IGPU" == true && "$SCAN_HAS_AMD_DGPU" == true ]]; then
echo -e "${YELLOW}[NOTE]${NC} AMD iGPU + AMD dGPU detected."
echo " DaVinci Resolve should use the discrete GPU automatically."
- echo " If it uses the wrong GPU, launch with: DRI_PRIME=1 davinci-resolve"
- ((warnings++))
+ echo " If it uses the wrong GPU, the launcher pins via PCI tag (DRI_PRIME=pci-DDDD_BB_DD_F)"
+ warnings=$((warnings+1))
fi
-
+
# Intel iGPU + AMD dGPU
if [[ "$SCAN_HAS_INTEL_IGPU" == true && "$SCAN_HAS_AMD_DGPU" == true ]]; then
echo -e "${YELLOW}[NOTE]${NC} Intel iGPU + AMD dGPU detected."
- echo " You may need to launch with: DRI_PRIME=1 davinci-resolve"
+ echo " You may need to launch with: DRI_PRIME=pci-DDDD_BB_DD_F davinci-resolve (use lspci to find the AMD bus)"
echo " The launcher script will be configured for this."
- ((warnings++))
+ warnings=$((warnings+1))
fi
-
+
# Intel iGPU + NVIDIA dGPU
if [[ "$SCAN_HAS_INTEL_IGPU" == true && "$SCAN_HAS_NVIDIA_DGPU" == true ]]; then
echo -e "${YELLOW}[NOTE]${NC} Intel iGPU + NVIDIA dGPU (Optimus) detected."
echo " For NVIDIA GPU: use prime-run or __NV_PRIME_RENDER_OFFLOAD=1"
echo " Consider using NVIDIA GPU for better Resolve performance."
- ((warnings++))
+ warnings=$((warnings+1))
fi
-
+
# AMD iGPU + NVIDIA dGPU
if [[ "$SCAN_HAS_AMD_IGPU" == true && "$SCAN_HAS_NVIDIA_DGPU" == true ]]; then
echo -e "${YELLOW}[NOTE]${NC} AMD iGPU + NVIDIA dGPU detected."
echo " For NVIDIA GPU: use prime-run or __NV_PRIME_RENDER_OFFLOAD=1"
- ((warnings++))
+ warnings=$((warnings+1))
fi
-
+
# Check if PRIME is available
if [[ "$SCAN_PRIME_AVAILABLE" == true ]]; then
echo -e "${GREEN}[OK]${NC} PRIME GPU switching is available (multiple render nodes detected)."
else
echo -e "${YELLOW}[WARNING]${NC} PRIME switching may not be configured correctly."
- ((warnings++))
+ warnings=$((warnings+1))
fi
-
+
echo ""
fi
-
+
# Check GPU vendor
if [[ "$SCAN_GPU_VENDOR" != "AMD" && "$SCAN_HAS_AMD_DGPU" != true ]]; then
if [[ "$SCAN_GPU_VENDOR" == "NVIDIA" ]]; then
echo -e "${YELLOW}[NOTE]${NC} NVIDIA GPU detected. This script is optimized for AMD."
echo " NVIDIA GPUs work well with Resolve but use different drivers (nvidia + CUDA)."
- ((warnings++))
+ warnings=$((warnings+1))
elif [[ "$SCAN_GPU_VENDOR" == "Intel" ]]; then
echo -e "${YELLOW}[WARNING]${NC} Only Intel GPU detected. DaVinci Resolve has limited Intel support."
- ((warnings++))
+ warnings=$((warnings+1))
else
echo -e "${YELLOW}[WARNING]${NC} GPU vendor not recognized. This script is optimized for AMD GPUs."
- ((warnings++))
+ warnings=$((warnings+1))
fi
fi
-
+
# Check Mesa for RDNA 4
if [[ "$SCAN_IS_RDNA4" == true && $SCAN_MESA_MAJOR -lt 25 ]]; then
echo -e "${YELLOW}[WARNING]${NC} Mesa $SCAN_MESA_VERSION may not fully support RDNA 4. Consider updating."
- ((warnings++))
+ warnings=$((warnings+1))
fi
-
+
# Check OpenCL
if [[ "$SCAN_OPENCL_INSTALLED" == true && "$SCAN_AMD_OPENCL_WORKING" == false ]]; then
echo -e "${YELLOW}[WARNING]${NC} OpenCL installed but AMD platform not detected. May need reconfiguration."
- ((warnings++))
+ warnings=$((warnings+1))
fi
# RDNA4 info
@@ -744,31 +832,31 @@ analyze_scan_results() {
else
echo " Using official Arch ROCm packages"
fi
-
+
# Check disk space (DaVinci Resolve needs ~3GB, opencl-amd ~500MB)
if [[ $SCAN_ROOT_FREE_GB -lt 5 ]]; then
echo -e "${RED}[ISSUE]${NC} Low disk space on root (${SCAN_ROOT_FREE_GB}GB). Need at least 5GB free."
- ((issues++))
+ issues=$((issues+1))
fi
-
+
# Check AUR helper
if [[ -z "$SCAN_AUR_HELPER" ]]; then
echo -e "${RED}[ISSUE]${NC} No AUR helper found. Install yay or paru first."
- ((issues++))
+ issues=$((issues+1))
fi
-
+
# Check display server
if [[ "$SCAN_DISPLAY_SERVER" == "None/TTY" ]]; then
echo -e "${YELLOW}[WARNING]${NC} No display server detected. Run this script from a graphical session."
- ((warnings++))
+ warnings=$((warnings+1))
fi
-
+
# Check existing Resolve installation
if [[ "$SCAN_RESOLVE_INSTALLED" == true ]]; then
echo -e "${YELLOW}[NOTE]${NC} DaVinci Resolve already installed (v${SCAN_RESOLVE_VERSION}). Will update/reconfigure."
- ((warnings++))
+ warnings=$((warnings+1))
fi
-
+
# Summary
echo ""
if [[ $issues -eq 0 && $warnings -eq 0 ]]; then
@@ -779,7 +867,7 @@ analyze_scan_results() {
echo -e "${RED}✗ $issues issue(s) and $warnings warning(s) detected.${NC}"
echo -e "${RED} Please resolve issues before continuing.${NC}"
fi
-
+
echo ""
return $issues
}
@@ -790,255 +878,98 @@ analyze_scan_results() {
build_package_list() {
header "Building Package List"
-
+
# Arrays for packages to install
PACMAN_PACKAGES=()
AUR_PACKAGES=()
SKIP_PACKAGES=()
-
- # Core graphics packages
- # Note: libva-mesa-driver and mesa-vdpau are now merged into mesa package
- local core_graphics=(
- "mesa"
- "glu"
- )
-
- for pkg in "${core_graphics[@]}"; do
- if is_pkg_installed "$pkg"; then
- SKIP_PACKAGES+=("$pkg")
- else
- PACMAN_PACKAGES+=("$pkg")
- fi
- done
-
- # OpenCL/ROCm - based on OPENCL_PROVIDER configuration
- if [[ "$OPENCL_PROVIDER" == "rocm-full" ]]; then
- # Full ROCm stack from official Arch repos (recommended for RDNA4)
- info "Using full ROCm stack (official Arch repos)"
- # Check if already installed and working
- if [[ "$SCAN_AMD_OPENCL_WORKING" == true && "$SCAN_OPENCL_PROVIDER" == rocm-full* ]]; then
- info "ROCm already configured correctly"
- SKIP_PACKAGES+=("rocm-opencl-runtime" "rocm-hip-runtime" "rocm-core")
- else
- # Core ROCm packages from official repos
- local rocm_packages=(
- "rocm-core"
- "rocm-opencl-runtime"
- "rocm-hip-runtime"
- "hsa-rocr"
- "rocminfo"
- "rocm-smi-lib"
+ # ---- Build/extraction tools (one-time, used by install step) ----
+ # Resolve ships as a ZIP containing a .run AppImage; we extract, patchelf,
+ # rsync to /opt/resolve, and update desktop/icon caches afterward.
+ local tools=(
+ unzip patchelf libarchive xdg-user-dirs desktop-file-utils
+ file gtk-update-icon-cache rsync
+ )
+
+ # ---- Resolve runtime deps NOT bundled in the AppImage ----
+ # Resolve bundles its own copies of Qt5, libpng12, libxcb-*, etc. and we
+ # patch RPATH so they're found in /opt/resolve/libs. The few libs below
+ # genuinely have to come from the host system.
+ local runtime=(
+ libxcrypt-compat # provides libcrypt.so.1 (Arch dropped it)
+ ffmpeg4.4 # Resolve links against this older FFmpeg ABI
+ glu # OpenGL Utility (3D rendering)
+ fuse2 # AppImage runtime compat
+ mesa # graphics stack (usually already present)
+ )
+
+ # ---- Display/Wayland compat for Hyprland ----
+ local display=(
+ xorg-xwayland # Resolve has no native Wayland support
+ xdg-desktop-portal
+ xdg-desktop-portal-gtk
+ )
+ if [[ "$SCAN_IS_HYBRID" == true ]]; then
+ display+=(switcheroo-control)
+ fi
+
+ # ---- AMD-specific OpenCL provider ----
+ # rocm-pinned-7.1.1 is the default and only currently-working path with
+ # DaVinci Resolve. The actual install of the 7.1.1 packages happens in
+ # install_rocm_pinned() (downloads from Arch Linux Archive).
+ local amd_opencl=()
+ case "$OPENCL_PROVIDER" in
+ rocm-pinned-7.1.1)
+ info "Using ROCm 7.1.1 pinned (working stack for DaVinci Resolve on AMD)"
+ # ocl-icd provides libOpenCL.so.1 loader. rocminfo for diagnostics.
+ # rocm-smi-lib for power/clock monitoring. rocm-* 7.1.1 are
+ # installed by install_rocm_pinned() below.
+ amd_opencl=(ocl-icd rocminfo rocm-smi-lib)
+ ;;
+ rocm-full)
+ warn "rocm-full = ROCm 7.2.x - KNOWN BROKEN with DaVinci Resolve as of May 2026"
+ warn " See https://github.com/ROCm/ROCm/issues/5982"
+ warn " Switch OPENCL_PROVIDER to 'rocm-pinned-7.1.1' for the working stack."
+ amd_opencl=(
+ rocm-core rocm-opencl-runtime rocm-hip-runtime
+ hsa-rocr rocminfo rocm-smi-lib
)
+ ;;
+ opencl-amd)
+ warn "opencl-amd = AUR ROCm 7.2.x - KNOWN BROKEN with DaVinci Resolve as of May 2026"
+ warn " Same ABI bug as rocm-full. Switch to 'rocm-pinned-7.1.1' for working stack."
+ amd_opencl=(ocl-icd)
+ AUR_PACKAGES+=(opencl-amd)
+ ;;
+ *)
+ error "Unknown OPENCL_PROVIDER: '$OPENCL_PROVIDER'"
+ ;;
+ esac
- for pkg in "${rocm_packages[@]}"; do
- if is_pkg_installed "$pkg"; then
- SKIP_PACKAGES+=("$pkg")
- else
- PACMAN_PACKAGES+=("$pkg")
- fi
- done
- fi
-
- # Remove conflicting AUR package if present
- if is_pkg_installed "opencl-amd"; then
- warn "opencl-amd (AUR) will be replaced with rocm-opencl-runtime"
- fi
- else
- # AUR opencl-amd (legacy option)
- info "Using opencl-amd (AUR package)"
- if [[ "$SCAN_AMD_OPENCL_WORKING" == true && "$SCAN_OPENCL_PROVIDER" == "opencl-amd" ]]; then
- info "OpenCL already configured correctly with opencl-amd"
- SKIP_PACKAGES+=("opencl-amd")
- else
- if ! is_pkg_installed "ocl-icd"; then
- PACMAN_PACKAGES+=("ocl-icd")
- else
- SKIP_PACKAGES+=("ocl-icd")
- fi
- AUR_PACKAGES+=("opencl-amd")
- fi
- fi
-
- # System libraries (includes davincibox dependencies mapped to Arch packages)
- # Note: gtk2 moved to AUR on Arch (late 2024)
- local system_libs=(
- "libxcrypt-compat"
- "fuse2"
- "fuse3"
- "libc++"
- "libc++abi"
- "patchelf"
- # Additional libraries from davincibox
- "alsa-lib"
- "apr"
- "apr-util"
- "libglvnd"
- "libice"
- "libsm"
- "librsvg"
- "libxcursor"
- "libxfixes"
- "libxi"
- "libxinerama"
- "libxkbcommon-x11"
- "libxkbfile"
- "libxrandr"
- "libxtst"
- "libxxf86vm"
- "lshw"
- "mtdev"
- "nss"
- "libpulse"
- "python-gobject"
- "gdk-pixbuf2"
- )
-
- for pkg in "${system_libs[@]}"; do
- if is_pkg_installed "$pkg"; then
- SKIP_PACKAGES+=("$pkg")
- else
- PACMAN_PACKAGES+=("$pkg")
- fi
- done
-
- # Qt packages
- # Note: qt5-webengine and qt5-websockets moved to AUR on Arch (Qt5 deprecated in favor of Qt6)
- local qt_packages=(
- "qt5-x11extras"
- "qt5-svg"
- "qt5-quickcontrols2"
- "qt5-multimedia"
- )
-
- # DaVinci Resolve runtime dependencies (from AUR PKGBUILD)
- local resolve_deps=(
- "python-numpy"
- "onetbb" # Was 'tbb', renamed on Arch
- "xmlsec"
- "gst-plugins-bad-libs"
- "luajit"
- )
-
- for pkg in "${qt_packages[@]}"; do
- if is_pkg_installed "$pkg"; then
- SKIP_PACKAGES+=("$pkg")
- else
- PACMAN_PACKAGES+=("$pkg")
- fi
- done
-
- for pkg in "${resolve_deps[@]}"; do
- if is_pkg_installed "$pkg"; then
- SKIP_PACKAGES+=("$pkg")
- else
- PACMAN_PACKAGES+=("$pkg")
- fi
- done
-
- # Display packages (includes xcb-util packages from davincibox)
- local display_packages=(
- "xorg-xwayland"
- "xdg-desktop-portal"
- "xdg-desktop-portal-gtk"
- # XCB utilities from davincibox
- "xcb-util"
- "xcb-util-cursor"
- "xcb-util-image"
- "xcb-util-keysyms"
- "xcb-util-renderutil"
- "xcb-util-wm"
- # GPU switching for hybrid systems
- "switcheroo-control"
- )
-
- for pkg in "${display_packages[@]}"; do
- if is_pkg_installed "$pkg"; then
- SKIP_PACKAGES+=("$pkg")
- else
- PACMAN_PACKAGES+=("$pkg")
- fi
- done
-
- # Audio packages - smart selection based on current audio server
+ # ---- Audio (smart-pick based on detected server) ----
+ local audio=()
if [[ "$SCAN_AUDIO_SERVER" == *"PipeWire"* ]]; then
- info "PipeWire detected - using pipewire-pulse for audio"
- if ! is_pkg_installed "pipewire-pulse"; then
- PACMAN_PACKAGES+=("pipewire-pulse")
- else
- SKIP_PACKAGES+=("pipewire-pulse")
- fi
- # Also need ALSA bridge for some Resolve functionality
- if ! is_pkg_installed "pipewire-alsa"; then
- PACMAN_PACKAGES+=("pipewire-alsa")
- fi
+ info "PipeWire detected - installing pipewire-pulse + pipewire-alsa"
+ audio=(pipewire-pulse pipewire-alsa)
else
- info "PulseAudio/other detected - using pulseaudio-alsa"
- if ! is_pkg_installed "pulseaudio-alsa"; then
- PACMAN_PACKAGES+=("pulseaudio-alsa")
- else
- SKIP_PACKAGES+=("pulseaudio-alsa")
- fi
+ info "PulseAudio detected - installing pulseaudio-alsa"
+ audio=(pulseaudio-alsa)
fi
-
- # Diagnostic tools
- local diag_tools=(
- "clinfo"
- "mesa-utils"
- "expac"
- "python-distro"
- "unzip"
- )
-
- for pkg in "${diag_tools[@]}"; do
+
+ # ---- Diagnostics ----
+ local diag=(clinfo mesa-utils expac python-distro)
+
+ # Combine and split into "need install" vs "skip"
+ for pkg in "${tools[@]}" "${runtime[@]}" "${display[@]}" \
+ "${amd_opencl[@]}" "${audio[@]}" "${diag[@]}"; do
if is_pkg_installed "$pkg"; then
SKIP_PACKAGES+=("$pkg")
else
PACMAN_PACKAGES+=("$pkg")
fi
done
-
- # AUR packages (packages moved from official repos)
- # gtk2 - moved to AUR late 2024
- if ! is_pkg_installed "gtk2"; then
- AUR_PACKAGES+=("gtk2")
- else
- SKIP_PACKAGES+=("gtk2")
- fi
- # qt5-webengine - moved to AUR (Qt5 deprecated)
- # Use binary version to avoid 30+ min compile time
- if ! is_pkg_installed "qt5-webengine" && ! is_pkg_installed "qt5-webengine-bin"; then
- AUR_PACKAGES+=("qt5-webengine-bin")
- else
- SKIP_PACKAGES+=("qt5-webengine")
- fi
-
- # qt5-websockets - moved to AUR (Qt5 deprecated)
- if ! is_pkg_installed "qt5-websockets"; then
- AUR_PACKAGES+=("qt5-websockets")
- else
- SKIP_PACKAGES+=("qt5-websockets")
- fi
-
- if ! is_pkg_installed "libpng12"; then
- AUR_PACKAGES+=("libpng12")
- else
- SKIP_PACKAGES+=("libpng12")
- fi
-
- # ffmpeg4.4 is now in official repos (extra)
- if ! is_pkg_installed "ffmpeg4.4"; then
- PACMAN_PACKAGES+=("ffmpeg4.4")
- else
- SKIP_PACKAGES+=("ffmpeg4.4")
- fi
-
- # DaVinci Resolve itself
- if [[ "$SCAN_RESOLVE_INSTALLED" == false ]]; then
- AUR_PACKAGES+=("davinci-resolve")
- fi
-
# Display summary
echo -e "${BOLD}Packages to install from official repos:${NC}"
if [[ ${#PACMAN_PACKAGES[@]} -gt 0 ]]; then
@@ -1046,7 +977,7 @@ build_package_list() {
else
echo " (none needed)"
fi
-
+
echo ""
echo -e "${BOLD}Packages to install from AUR:${NC}"
if [[ ${#AUR_PACKAGES[@]} -gt 0 ]]; then
@@ -1054,7 +985,7 @@ build_package_list() {
else
echo " (none needed)"
fi
-
+
echo ""
echo -e "${BOLD}Packages already installed (skipping):${NC}"
if [[ ${#SKIP_PACKAGES[@]} -gt 0 ]]; then
@@ -1062,7 +993,7 @@ build_package_list() {
else
echo " (none)"
fi
-
+
echo ""
}
@@ -1108,9 +1039,9 @@ install_aur_packages() {
info "No AUR packages to install."
return 0
fi
-
+
header "Installing AUR Packages"
-
+
# Handle OpenCL conflicts
if [[ " ${AUR_PACKAGES[*]} " =~ " opencl-amd " ]]; then
# Check for conflicting packages
@@ -1130,66 +1061,153 @@ install_aur_packages() {
fi
fi
fi
-
- # Handle libpng12 GPG key
- if [[ " ${AUR_PACKAGES[*]} " =~ " libpng12 " ]]; then
- info "Importing GPG key for libpng12..."
- gpg --recv-keys F54984BFA16C640F 2>/dev/null || true
- fi
-
- # Install AUR packages (except davinci-resolve which needs special handling)
- local aur_without_resolve=()
- for pkg in "${AUR_PACKAGES[@]}"; do
- if [[ "$pkg" != "davinci-resolve" ]]; then
- aur_without_resolve+=("$pkg")
- fi
- done
-
- if [[ ${#aur_without_resolve[@]} -gt 0 ]]; then
- info "Installing AUR dependencies..."
- $SCAN_AUR_HELPER -S --needed --noconfirm "${aur_without_resolve[@]}"
- fi
-
+
+ info "Installing AUR packages..."
+ $SCAN_AUR_HELPER -S --needed --noconfirm "${AUR_PACKAGES[@]}"
+
success "AUR packages installed."
}
+install_rocm_pinned() {
+ # Install ROCm 7.1.1 from the Arch Linux Archive (ALA) and pin it in
+ # /etc/pacman.conf IgnorePkg.
+ #
+ # Why: ROCm 7.2.x (current Arch extra) breaks DaVinci Resolve - the
+ # OpenCL clCreateContext call fails on AMD GPUs after the 7.2 update.
+ # See ROCm/ROCm#5982 (filed 2026-02-19, still open).
+ # Confirmed broken on 760M iGPU, 7800 XT, RX 9060 XT (this user).
+ # 7.1.1 is the last working release.
+ #
+ # Why not opencl-amd: it bundles its own 7.2.x ROCm internally and
+ # has the same ABI bug. It also conflicts with rocm-opencl-runtime
+ # so you can only have one or the other.
+ #
+ # When ROCm 7.3+ ships with the fix, lift the pin:
+ # sudo sed -i '/^IgnorePkg.*rocm-/d' /etc/pacman.conf
+ # sudo pacman -Syu
+
+ [[ "$OPENCL_PROVIDER" != "rocm-pinned-7.1.1" ]] && return 0
+
+ header "Installing ROCm 7.1.1 (pinned)"
+
+ # If the working stack is already present at the right version, skip.
+ local need_install=0
+ for pkg in rocm-core rocm-device-libs rocm-llvm rocm-opencl-runtime comgr; do
+ local ver
+ ver=$(pacman -Q "$pkg" 2>/dev/null | awk '{print $2}')
+ if [[ -z "$ver" || ! "$ver" =~ 7\.1\.1 ]]; then
+ need_install=1
+ break
+ fi
+ done
+ if [[ "$need_install" == 0 ]] && pacman -Q spirv-llvm-translator 2>/dev/null | grep -q "21.1.3"; then
+ info "ROCm 7.1.1 stack already present at correct versions - skipping ALA download."
+ else
+ # Remove conflicting package: opencl-amd bundles ROCm 7.2.1 and
+ # conflicts with rocm-opencl-runtime
+ if pacman -Q opencl-amd &>/dev/null; then
+ warn "Removing opencl-amd (AUR, conflicts with rocm-opencl-runtime)..."
+ sudo pacman -Rns opencl-amd --noconfirm 2>/dev/null || true
+ fi
+ if pacman -Q opencl-amd-debug &>/dev/null; then
+ sudo pacman -Rns opencl-amd-debug --noconfirm 2>/dev/null || true
+ fi
+
+ # Download the 6 packages from Arch Linux Archive
+ local ala="https://archive.archlinux.org/packages"
+ local pkgs=(
+ "${ala}/r/rocm-core/rocm-core-7.1.1-1-x86_64.pkg.tar.zst"
+ "${ala}/r/rocm-device-libs/rocm-device-libs-2:7.1.1-1-x86_64.pkg.tar.zst"
+ "${ala}/r/rocm-llvm/rocm-llvm-2:7.1.1-1-x86_64.pkg.tar.zst"
+ "${ala}/r/rocm-opencl-runtime/rocm-opencl-runtime-7.1.1-1-x86_64.pkg.tar.zst"
+ "${ala}/c/comgr/comgr-2:7.1.1-1-x86_64.pkg.tar.zst"
+ "${ala}/s/spirv-llvm-translator/spirv-llvm-translator-21.1.3-1-x86_64.pkg.tar.zst"
+ )
+
+ local tmpdir
+ tmpdir=$(mktemp -d -t rocm-pinned-XXXXXX)
+ local trap_old
+ # shellcheck disable=SC2064
+ trap "rm -rf '$tmpdir'" EXIT
+
+ info "Downloading ROCm 7.1.1 packages from Arch Linux Archive..."
+ local downloaded=()
+ for url in "${pkgs[@]}"; do
+ local fname
+ fname=$(basename "$url")
+ info " $fname"
+ if curl -fsSL --output "$tmpdir/$fname" "$url"; then
+ downloaded+=("$tmpdir/$fname")
+ else
+ error "Failed to download $url"
+ fi
+ done
+
+ # numactl + gflags are runtime deps usually already installed
+ sudo pacman -S --needed --noconfirm numactl gflags 2>&1 | tail -3 || true
+
+ info "Installing pinned ROCm 7.1.1 packages..."
+ sudo pacman -U --noconfirm "${downloaded[@]}" \
+ || error "Failed to install pinned ROCm 7.1.1 packages from ALA - aborting before launcher/config steps run against a broken stack."
+
+ rm -rf "$tmpdir"
+ trap - EXIT
+ fi
+
+ # Pin in /etc/pacman.conf [options] IgnorePkg so future -Syu doesn't
+ # break Resolve again. Idempotent.
+ local pin_pkgs="rocm-core rocm-device-libs rocm-llvm rocm-opencl-runtime comgr spirv-llvm-translator"
+ if grep -q "^IgnorePkg.*rocm-core" /etc/pacman.conf; then
+ info "IgnorePkg already pins ROCm packages."
+ else
+ info "Adding IgnorePkg pin for ROCm 7.1.1 packages..."
+ # Insert immediately after [options] section header
+ sudo sed -i "/^\[options\]/a IgnorePkg = ${pin_pkgs}" /etc/pacman.conf
+ success "Pinned in /etc/pacman.conf [options]."
+ fi
+
+ success "ROCm 7.1.1 installed and pinned."
+}
+
install_davinci_resolve() {
+ # NVIDIA-mirrored install path:
+ # 1. Find ZIP in ~/Downloads
+ # 2. Disk-space check (~10 GB free)
+ # 3. mktemp + trap to clean up on any exit
+ # 4. unzip ZIP -> find .run -> --appimage-extract -> squashfs-root
+ # 5. Replace bundled glib/gio/gmodule with system symlinks
+ # (KEEP vendored libc++/libc++abi - removing breaks Resolve)
+ # 6. Extract DaVinci panel-framework tarball if present
+ # 7. rsync squashfs-root to /opt/resolve
+ # 8. patchelf --set-rpath on every ELF in /opt/resolve
+ # 9. libcrypt.so.1 fallback symlink
+ # 10. Install desktop entries / icons / udev rules system-wide
+ #
+ # No AUR PKGBUILD, no qt5-webengine source build. Resolve's bundled Qt5
+ # is used via RPATH. Pacman does not track this install - to remove:
+ # `sudo rm -rf /opt/resolve` and the desktop/icon/udev files.
+
if [[ "$SCAN_RESOLVE_INSTALLED" == true ]]; then
- info "DaVinci Resolve already installed. Skipping installation."
+ info "DaVinci Resolve already installed at /opt/resolve."
info "Will apply workarounds and configuration updates."
return 0
fi
-
+
header "Installing DaVinci Resolve"
-
- # Find installer (handle filenames with spaces properly)
+
+ # ---- Locate the ZIP installer ----
local downloads_dir="$HOME/Downloads"
- local resolve_run="" resolve_zip=""
-
- while IFS= read -r -d '' file; do
- resolve_run="$file"
- done < <(find "$downloads_dir" -maxdepth 1 -name "DaVinci_Resolve_*_Linux.run" -type f -print0 2>/dev/null | sort -zV)
-
+ local resolve_zip=""
while IFS= read -r -d '' file; do
resolve_zip="$file"
done < <(find "$downloads_dir" -maxdepth 1 -name "DaVinci_Resolve_*_Linux.zip" -type f -print0 2>/dev/null | sort -zV)
-
- # PKGBUILD expects the ZIP file, not the extracted .run
- # If we only have .run, we can't use the AUR PKGBUILD easily
- if [[ -z "$resolve_zip" && -n "$resolve_run" ]]; then
- warn "Only .run file found, but PKGBUILD expects .zip"
- warn "Please download the ZIP file from Blackmagic website"
- return 1
- fi
-
+
if [[ -z "$resolve_zip" ]]; then
echo ""
warn "DaVinci Resolve ZIP not found in ~/Downloads"
- echo ""
- echo "Please download it:"
echo " 1. Go to: https://www.blackmagicdesign.com/products/davinciresolve"
- echo " 2. Click 'Download' → 'DaVinci Resolve' (Free)"
- echo " 3. Select 'Linux' and save ZIP to ~/Downloads"
+ echo " 2. Click 'Download' -> 'DaVinci Resolve' (Free)"
+ echo " 3. Select 'Linux' and save the ZIP to ~/Downloads"
echo ""
read -p "Open download page? [Y/n] " -n 1 -r
echo
@@ -1198,10 +1216,8 @@ install_davinci_resolve() {
fi
return 1
fi
-
success "Found installer: $resolve_zip"
- # Check version for RDNA 4 compatibility
local resolve_version=$(basename "$resolve_zip" | grep -oP 'Resolve_\K[0-9]+\.[0-9]+(\.[0-9]+)?' || echo "")
if [[ "$SCAN_IS_RDNA4" == true && -n "$resolve_version" ]]; then
local major=$(echo "$resolve_version" | cut -d'.' -f1)
@@ -1209,175 +1225,233 @@ install_davinci_resolve() {
warn "DaVinci Resolve $resolve_version may not work with RDNA 4 (need 20.x+)"
fi
fi
-
- # Build via AUR
- local build_dir
- # Use home directory for build (tmpfs /tmp may be too small)
- build_dir=$(mktemp -d -p "$HOME/.cache" davinci-build.XXXXXX)
+
+ # ---- Disk space check (~10 GB needed for staged extraction) ----
+ local needed_gb=10
+ local free_kb=$(df --output=avail -k "$downloads_dir" | tail -n1)
+ local free_gb=$((free_kb / 1024 / 1024))
+ if (( free_gb < needed_gb )); then
+ error "Not enough free space in $downloads_dir: ${free_gb} GiB < ${needed_gb} GiB"
+ fi
+
+ # ---- Stage extraction in a temp dir under ~/Downloads ----
+ local workdir
+ workdir=$(mktemp -d -p "$downloads_dir" .resolve-extract-XXXXXXXX)
local original_dir="$PWD"
- info "Building in $build_dir..."
-
- # Cleanup function for build directory
- cleanup_build() {
+ cleanup_resolve_build() {
cd "$original_dir" 2>/dev/null || cd ~
- rm -rf "$build_dir" 2>/dev/null
- }
- trap cleanup_build EXIT
-
- cd "$build_dir"
- git clone https://aur.archlinux.org/davinci-resolve.git
- cd davinci-resolve
-
- # Copy the ZIP file (PKGBUILD expects ZIP, not .run)
- # Rename to match expected filename: DaVinci_Resolve_${pkgver}_Linux.zip
- local expected_zip="DaVinci_Resolve_${resolve_version}_Linux.zip"
- cp "$resolve_zip" "$expected_zip"
-
- # Fix Arch package renames in PKGBUILD
- # tbb → onetbb (Intel TBB renamed on Arch)
- sed -i "s/'tbb'/'onetbb'/g" PKGBUILD
-
- # Update PKGBUILD version if needed
- local version_updated=false
- if [[ -n "$resolve_version" ]]; then
- local pkgbuild_ver=$(grep "^pkgver=" PKGBUILD | cut -d'=' -f2)
- if [[ "$resolve_version" != "$pkgbuild_ver" ]]; then
- info "Updating PKGBUILD version to $resolve_version..."
- sed -i "s/^pkgver=.*/pkgver=$resolve_version/" PKGBUILD
- version_updated=true
- # Use updpkgsums if available, otherwise we'll skip checksums during build
- if command -v updpkgsums &>/dev/null; then
- info "Updating checksums..."
- updpkgsums
- version_updated=false # checksums are now correct
- else
- info "Will skip checksum verification (version mismatch, updpkgsums not available)..."
- fi
+ if [[ -n "${workdir:-}" && -d "$workdir" ]]; then
+ info "Cleaning up extraction directory..."
+ rm -rf "$workdir" 2>/dev/null || true
fi
+ }
+ trap cleanup_resolve_build EXIT
+
+ info "Unpacking ZIP to $workdir ..."
+ unzip -q "$resolve_zip" -d "$workdir"
+
+ local run_file
+ run_file=$(find "$workdir" -maxdepth 2 -type f -name 'DaVinci_Resolve_*_Linux.run' | head -n1 || true)
+ [[ -n "$run_file" ]] || error "Could not find the .run installer inside the ZIP"
+ chmod +x "$run_file"
+
+ local ex_dir=$(dirname "$run_file")
+ info "Extracting AppImage payload..."
+ if ! ( cd "$ex_dir" && "./$(basename "$run_file")" --appimage-extract >/dev/null ); then
+ error "Failed to extract AppImage payload from $run_file"
fi
- info "Building package (this takes several minutes)..."
- if [[ "$version_updated" == true ]]; then
- makepkg -si --noconfirm --skipchecksums
- else
- makepkg -si --noconfirm
- fi
+ local appdir="$ex_dir/squashfs-root"
+ [[ -d "$appdir" ]] || error "Extraction produced no squashfs-root directory"
+ [[ -s "$appdir/bin/resolve" ]] || error "resolve binary missing or zero-size after extraction"
- # Cleanup
- cleanup_build
- trap - EXIT
-
- success "DaVinci Resolve installed."
-}
+ chmod -R u+rwX,go+rX,go-w "$appdir" 2>/dev/null || warn "Could not normalize all permissions"
-apply_patchelf_fix() {
- # Davincibox-style fix: use patchelf to add system library dependencies
- # This is cleaner than LD_PRELOAD and survives across sessions
- header "Applying Patchelf Fix (Davincibox Method)"
-
- local resolve_bin="/opt/resolve/bin"
-
- if [[ ! -d "$resolve_bin" ]]; then
- warn "Resolve bin directory not found. Skipping patchelf fix."
- return
- fi
-
- if ! command -v patchelf &>/dev/null; then
- warn "patchelf not installed. Falling back to library move method."
- apply_glib_fix_fallback
- return
- fi
-
- # Check if already patched by looking for added dependencies
- if patchelf --print-needed "$resolve_bin/resolve" 2>/dev/null | grep -q "libglib-2.0.so.0"; then
- info "Patchelf fix already applied."
- return
- fi
-
- info "Patching DaVinci Resolve binaries with system library dependencies..."
-
- # Determine library path (Arch uses /usr/lib, Fedora uses /usr/lib64)
- local lib_path="/usr/lib"
- [[ -d "/usr/lib64" && -f "/usr/lib64/libglib-2.0.so.0" ]] && lib_path="/usr/lib64"
-
- # Libraries to add as dependencies (forces use of system libs over bundled)
- # Using full paths as davincibox does
- local libs_to_add=(
- "${lib_path}/libglib-2.0.so.0"
- "${lib_path}/libgio-2.0.so.0"
- "${lib_path}/libgmodule-2.0.so.0"
- "${lib_path}/libgdk_pixbuf-2.0.so.0"
+ # ---- ABI-safe bundled-library replacement ----
+ # Replace bundled glib family with system versions (stable C ABI -
+ # safe to swap and avoids the well-known Resolve+Arch glib clash).
+ #
+ # All five glib-family libs must be swapped together: GObject's vtable
+ # layout has to match the GLib it was built against, and GThread shares
+ # internal state with GLib. Mixing a system libglib with bundled
+ # libgobject means GObject calls into GLib symbols that have moved
+ # between versions (Arch ships glib2 2.88+, bundled GObject is from
+ # 2.68) and segfaults on the first signal emit / type registration.
+ # Symptoms: random crashes in file pickers, GIO async ops, gstreamer
+ # media import.
+ #
+ # KEEP vendored libc++/libc++abi - replacing them causes immediate crashes
+ # because Resolve was compiled against specific libc++ ABI versions.
+ info "Replacing bundled glib family (glib/gio/gmodule/gobject/gthread) with system versions..."
+ pushd "$appdir" >/dev/null
+ declare -A glib_libs=(
+ ["/usr/lib/libglib-2.0.so.0"]="libs/libglib-2.0.so.0"
+ ["/usr/lib/libgio-2.0.so.0"]="libs/libgio-2.0.so.0"
+ ["/usr/lib/libgmodule-2.0.so.0"]="libs/libgmodule-2.0.so.0"
+ ["/usr/lib/libgobject-2.0.so.0"]="libs/libgobject-2.0.so.0"
+ ["/usr/lib/libgthread-2.0.so.0"]="libs/libgthread-2.0.so.0"
)
-
- # Verify libraries exist
- for lib in "${libs_to_add[@]}"; do
- if [[ ! -f "$lib" ]]; then
- warn "Library not found: $lib"
- warn "Falling back to library names only..."
- libs_to_add=(
- "libglib-2.0.so.0"
- "libgio-2.0.so.0"
- "libgmodule-2.0.so.0"
- "libgdk_pixbuf-2.0.so.0"
- )
- break
+ for syslib in "${!glib_libs[@]}"; do
+ local target="${glib_libs[$syslib]}"
+ if [[ -e "$syslib" ]]; then
+ rm -f "$target" || true
+ ln -sf "$syslib" "$target" || warn "Failed to symlink $syslib -> $target"
+ else
+ warn "System library $syslib not found, keeping bundled version"
fi
done
- # Patch all executables in bin directory using find (like davincibox)
- info "Running: find $resolve_bin -executable -type f -exec patchelf ..."
-
- local patch_count=0
- while IFS= read -r -d '' binary; do
- # Skip if not an ELF binary
- file "$binary" 2>/dev/null | grep -q "ELF" || continue
-
- local patch_args=""
- for lib in "${libs_to_add[@]}"; do
- patch_args+=" --add-needed $lib"
- done
-
- if sudo patchelf $patch_args "$binary" 2>/dev/null; then
- ((patch_count++))
+ # Extract bundled DaVinci panel-framework (control surface support libs)
+ if [[ -d "share/panels" ]]; then
+ pushd "share/panels" >/dev/null
+ tar -zxf dvpanel-framework-linux-x86_64.tgz 2>/dev/null || true
+ mkdir -p "$appdir/libs"
+ find . -maxdepth 1 -type f -name '*.so' -exec mv -f {} "$appdir/libs" \; 2>/dev/null || true
+ if [[ -d lib ]]; then
+ find lib -type f -name '*.so*' -exec mv -f {} "$appdir/libs" \; 2>/dev/null || true
fi
- done < <(find "$resolve_bin" -executable -type f -print0 2>/dev/null)
-
- local patched=$patch_count
- local failed=0
-
- if [[ $patched -gt 0 ]]; then
- success "Patchelf fix applied to binaries."
- else
- warn "Patchelf fix may have failed. Applying fallback..."
- apply_glib_fix_fallback
- fi
-}
-
-apply_glib_fix_fallback() {
- # Fallback: move bundled glib libraries (original method)
- local resolve_libs="/opt/resolve/libs"
-
- if [[ ! -d "$resolve_libs" ]]; then
- warn "Resolve libs directory not found. Skipping."
- return
+ popd >/dev/null
fi
- # Check if already fixed
- if [[ -d "$resolve_libs/disabled-libraries" ]] && \
- [[ ! -f "$resolve_libs/libglib-2.0.so.0" ]]; then
- info "Glib fix (fallback) already applied."
- return
+ # AppImage launcher leftovers - we install to /opt/resolve, not run as AppImage
+ rm -f AppRun AppRun* 2>/dev/null || true
+ rm -rf installer installer* 2>/dev/null || true
+ mkdir -p bin
+ ln -sf "../BlackmagicRAWPlayer/BlackmagicRawAPI" "bin/" 2>/dev/null || true
+ popd >/dev/null
+
+ # ---- Install to /opt/resolve ----
+ info "Installing to /opt/resolve (rsync) ..."
+ sudo rm -rf /opt/resolve
+ sudo mkdir -p /opt/resolve
+ sudo rsync -a --delete "$appdir/" /opt/resolve/
+ sudo mkdir -p /opt/resolve/.license
+
+ # ---- RPATH patching ----
+ # Resolve's bundled binaries have RPATHs pointing to AppImage extraction
+ # paths that no longer exist. Patch every ELF (executable + shared object)
+ # to search /opt/resolve/libs/ and its plugin subdirectories.
+ info "Patching RPATH on every ELF in /opt/resolve (may take a minute)..."
+ local rpath_dirs=(
+ "libs" "libs/plugins/sqldrivers" "libs/plugins/xcbglintegrations"
+ "libs/plugins/imageformats" "libs/plugins/platforms" "libs/Fusion"
+ "plugins" "bin"
+ "BlackmagicRAWSpeedTest/BlackmagicRawAPI"
+ "BlackmagicRAWSpeedTest/plugins/platforms"
+ "BlackmagicRAWSpeedTest/plugins/imageformats"
+ "BlackmagicRAWSpeedTest/plugins/mediaservice"
+ "BlackmagicRAWSpeedTest/plugins/audio"
+ "BlackmagicRAWSpeedTest/plugins/xcbglintegrations"
+ "BlackmagicRAWSpeedTest/plugins/bearer"
+ "BlackmagicRAWPlayer/BlackmagicRawAPI"
+ "BlackmagicRAWPlayer/plugins/mediaservice"
+ "BlackmagicRAWPlayer/plugins/imageformats"
+ "BlackmagicRAWPlayer/plugins/audio"
+ "BlackmagicRAWPlayer/plugins/platforms"
+ "BlackmagicRAWPlayer/plugins/xcbglintegrations"
+ "BlackmagicRAWPlayer/plugins/bearer"
+ "Onboarding/plugins/xcbglintegrations" "Onboarding/plugins/qtwebengine"
+ "Onboarding/plugins/platforms" "Onboarding/plugins/imageformats"
+ "DaVinci Control Panels Setup/plugins/platforms"
+ "DaVinci Control Panels Setup/plugins/imageformats"
+ "DaVinci Control Panels Setup/plugins/bearer"
+ "DaVinci Control Panels Setup/AdminUtility/PlugIns/DaVinciKeyboards"
+ "DaVinci Control Panels Setup/AdminUtility/PlugIns/DaVinciPanels"
+ )
+ local rpath_abs=""
+ for p in "${rpath_dirs[@]}"; do rpath_abs+="/opt/resolve/${p}:"; done
+ rpath_abs+="\$ORIGIN"
+
+ local patch_count=0 patch_fail=0 patch_skip=0
+ while IFS= read -r -d '' f; do
+ local file_info
+ file_info=$(file -b "$f" 2>/dev/null)
+ if [[ "$file_info" =~ ELF.*executable ]] || [[ "$file_info" =~ ELF.*shared\ object ]]; then
+ local current_rpath
+ current_rpath=$(patchelf --print-rpath "$f" 2>/dev/null || true)
+ if [[ "$current_rpath" == "$rpath_abs" ]]; then
+ patch_skip=$((patch_skip + 1))
+ continue
+ fi
+ if sudo patchelf --set-rpath "$rpath_abs" "$f" 2>/dev/null; then
+ patch_count=$((patch_count + 1))
+ else
+ patch_fail=$((patch_fail + 1))
+ local file_size=$(stat -c%s "$f" 2>/dev/null || echo 0)
+ if (( file_size > 33554432 )); then
+ warn "Failed to patch large file (>32MB): ${f##/opt/resolve/}"
+ fi
+ fi
+ fi
+ done < <(find /opt/resolve -type f -print0)
+ success "Patched RPATH: $patch_count files ($patch_fail failures, $patch_skip already correct)"
+
+ # ---- libcrypt.so.1 fallback symlink ----
+ # libxcrypt-compat already provides /usr/lib/libcrypt.so.1; symlink it
+ # into /opt/resolve/libs as a belt-and-braces fallback.
+ sudo ldconfig 2>/dev/null || true
+ if [[ -e /usr/lib/libcrypt.so.1 ]]; then
+ sudo ln -sf /usr/lib/libcrypt.so.1 /opt/resolve/libs/libcrypt.so.1
fi
- info "Moving bundled glib libraries (fallback method)..."
- sudo mkdir -p "$resolve_libs/disabled-libraries"
+ # ---- Desktop entries (system-wide) ----
+ info "Installing desktop entries, icons, and udev rules..."
+ declare -A desktop_files=(
+ ["/opt/resolve/share/DaVinciResolve.desktop"]="/usr/share/applications/DaVinciResolve.desktop"
+ ["/opt/resolve/share/DaVinciControlPanelsSetup.desktop"]="/usr/share/applications/DaVinciControlPanelsSetup.desktop"
+ ["/opt/resolve/share/blackmagicraw-player.desktop"]="/usr/share/applications/blackmagicraw-player.desktop"
+ ["/opt/resolve/share/blackmagicraw-speedtest.desktop"]="/usr/share/applications/blackmagicraw-speedtest.desktop"
+ )
+ for src in "${!desktop_files[@]}"; do
+ local dest="${desktop_files[$src]}"
+ if [[ -f "$src" ]]; then
+ sudo install -D -m 0644 "$src" "$dest"
+ # Critical: Resolve's bundled .desktop files have a literal
+ # "RESOLVE_INSTALL_LOCATION" placeholder that the official
+ # installer would substitute. Our manual copy doesn't, so the
+ # app menu launcher would do nothing. Substitute now.
+ sudo sed -i "s|RESOLVE_INSTALL_LOCATION|/opt/resolve|g" "$dest"
+ else
+ warn "Desktop file not found: $src"
+ fi
+ done
- # Use find to avoid glob pattern issues when no files match
- while IFS= read -r -d '' lib; do
- sudo mv "$lib" "$resolve_libs/disabled-libraries/" 2>/dev/null || true
- done < <(find "$resolve_libs" -maxdepth 1 -type f \( -name 'libglib-2.0.so*' -o -name 'libgio-2.0.so*' -o -name 'libgmodule-2.0.so*' \) -print0 2>/dev/null)
+ declare -A icon_files=(
+ ["/opt/resolve/graphics/DV_Resolve.png"]="/usr/share/icons/hicolor/128x128/apps/davinci-resolve.png"
+ ["/opt/resolve/graphics/DV_Panels.png"]="/usr/share/icons/hicolor/128x128/apps/davinci-resolve-panels-setup.png"
+ ["/opt/resolve/graphics/blackmagicraw-player_256x256_apps.png"]="/usr/share/icons/hicolor/256x256/apps/blackmagicraw-player.png"
+ ["/opt/resolve/graphics/blackmagicraw-speedtest_256x256_apps.png"]="/usr/share/icons/hicolor/256x256/apps/blackmagicraw-speedtest.png"
+ )
+ for src in "${!icon_files[@]}"; do
+ local dest="${icon_files[$src]}"
+ if [[ -f "$src" ]]; then
+ sudo install -D -m 0644 "$src" "$dest"
+ else
+ warn "Icon file not found: $src"
+ fi
+ done
- success "Glib fix (fallback) applied."
+ sudo update-desktop-database >/dev/null 2>&1 || true
+ sudo gtk-update-icon-cache -f /usr/share/icons/hicolor >/dev/null 2>&1 || true
+
+ # ---- udev rules for Blackmagic capture cards / control surfaces ----
+ for r in 99-BlackmagicDevices.rules 99-ResolveKeyboardHID.rules 99-DavinciPanel.rules; do
+ local src="/opt/resolve/share/etc/udev/rules.d/$r"
+ if [[ -f "$src" ]]; then
+ sudo install -D -m 0644 "$src" "/usr/lib/udev/rules.d/$r"
+ fi
+ done
+ sudo udevadm control --reload-rules 2>/dev/null && sudo udevadm trigger 2>/dev/null || true
+
+ # Cleanup extraction tree
+ cleanup_resolve_build
+ trap - EXIT
+
+ # Refresh scan flag so downstream functions see the install
+ SCAN_RESOLVE_INSTALLED=true
+ SCAN_RESOLVE_PATH="/opt/resolve"
+
+ success "DaVinci Resolve installed to /opt/resolve."
}
disable_opencl_decoders() {
@@ -1412,6 +1486,160 @@ disable_opencl_decoders() {
fi
}
+setup_tls_symlink() {
+ # Resolve's built-in extras downloader expects RHEL/CentOS cert path
+ # /etc/pki/tls instead of Arch's /etc/ssl. Symlink so updates work.
+ header "Configuring TLS Cert Path for Resolve"
+
+ if [[ -e /etc/pki/tls ]]; then
+ info "/etc/pki/tls already exists - skipping."
+ return
+ fi
+
+ sudo mkdir -p /etc/pki
+ sudo ln -sf /etc/ssl /etc/pki/tls
+ success "Linked /etc/pki/tls -> /etc/ssl"
+}
+
+patch_audio_backend() {
+ # Resolve ships with `Local.Audio.Type = DeckLink` in its system-wide
+ # config template. On systems without a Blackmagic DeckLink card this
+ # makes Resolve fail on first launch. Switch the default to ALSA.
+ header "Patching Resolve Audio Backend (DeckLink -> ALSA)"
+
+ local template="/opt/resolve/share/default-config.dat"
+ if [[ -f "$template" ]] && grep -q '^Local\.Audio\.Type = DeckLink$' "$template"; then
+ sudo sed -i 's|^Local\.Audio\.Type = DeckLink$|Local.Audio.Type = ALSA|' "$template"
+ success "Patched system template: $template"
+ elif [[ -f "$template" ]]; then
+ info "System template already patched or non-default."
+ else
+ warn "System template not found - skipping."
+ fi
+
+ local user_cfg="${HOME}/.local/share/DaVinciResolve/configs/config.dat"
+ if [[ -f "$user_cfg" ]] && grep -q '^Local\.Audio\.Type = DeckLink$' "$user_cfg"; then
+ cp "$user_cfg" "$user_cfg.bak.$(date +%s)"
+ sed -i 's|^Local\.Audio\.Type = DeckLink$|Local.Audio.Type = ALSA|' "$user_cfg"
+ success "Patched user config (backup .bak. created)"
+ fi
+}
+
+setup_snd_aloop() {
+ # Resolve's audio engine opens raw ALSA hw: devices and never uses ALSA's
+ # plugin layer (default/pulse/pipewire). When PipeWire owns every real
+ # card, Resolve's enumerator loops looking for a free PCM and renders
+ # never start. Loading snd-aloop gives Resolve a virtual card it can fully
+ # own; PipeWire ignores it. Strace evidence: 14k+ SNDRV_CTL_IOCTL_PCM_INFO
+ # ENXIO / 47k+ /dev/snd/controlCN ENOENT during a stuck render.
+ #
+ # Skip with RESOLVE_NO_ALOOP=1 (e.g. user has a dedicated audio interface).
+ header "snd-aloop Render-Blocker Fix"
+
+ if [[ "${RESOLVE_NO_ALOOP:-0}" == "1" ]]; then
+ info "Skipping snd-aloop setup (RESOLVE_NO_ALOOP=1)."
+ return
+ fi
+
+ # 1. Load module now
+ if lsmod | grep -qE '^snd_aloop'; then
+ info "snd-aloop already loaded."
+ else
+ if sudo modprobe snd-aloop 2>/dev/null; then
+ success "snd-aloop loaded for the current session."
+ else
+ warn "modprobe snd-aloop failed. Verify with: modinfo snd-aloop"
+ warn "On Arch this is part of linux/linux-zen/linux-lts kernel packages."
+ fi
+ fi
+
+ # 2. Persist across reboots
+ local aloop_conf="/etc/modules-load.d/snd-aloop.conf"
+ if [[ ! -f "$aloop_conf" ]] || ! grep -qx 'snd-aloop' "$aloop_conf" 2>/dev/null; then
+ echo 'snd-aloop' | sudo tee "$aloop_conf" >/dev/null
+ success "Wrote $aloop_conf (autoloads at boot)."
+ else
+ info "$aloop_conf already configured."
+ fi
+
+ # 3. PipeWire loopback bridge - sends aloop capture to system default sink
+ # so Resolve monitor audio is audible while editing.
+ local bridge_dir="${HOME}/.config/pipewire/pipewire.conf.d"
+ local bridge_file="${bridge_dir}/50-resolve-aloop-bridge.conf"
+ mkdir -p "$bridge_dir"
+ if [[ ! -f "$bridge_file" ]]; then
+ cat > "$bridge_file" <<'EOF'
+# DaVinci Resolve aloop monitor bridge - managed by install-davinci-resolve.sh
+# Bridges snd-aloop's capture side to the system default sink so Resolve's
+# monitor audio is audible while editing. Without this, renders complete but
+# you hear nothing during playback. Remove this file + restart PipeWire to
+# disable.
+context.modules = [
+ { name = libpipewire-module-loopback
+ args = {
+ node.description = "DaVinci Resolve aloop monitor bridge"
+ capture.props = {
+ node.name = "resolve-aloop-capture"
+ target.object = "alsa_input.platform-snd_aloop.0.analog-stereo"
+ node.passive = true
+ }
+ playback.props = {
+ node.name = "resolve-aloop-playback"
+ media.class = "Stream/Output/Audio"
+ }
+ }
+ }
+]
+EOF
+ success "Wrote $bridge_file (PipeWire loopback bridge)."
+ else
+ info "$bridge_file already in place."
+ fi
+
+ # 4. Wireplumber rule - keep aloop OUT of default-sink rotation.
+ # Without this, wireplumber promotes aloop to default whenever Resolve
+ # makes it RUNNING, and the bridge feeds aloop back into itself.
+ local wp_dir="${HOME}/.config/wireplumber/wireplumber.conf.d"
+ local wp_file="${wp_dir}/51-resolve-aloop-no-default.conf"
+ mkdir -p "$wp_dir"
+ if [[ ! -f "$wp_file" ]]; then
+ cat > "$wp_file" <<'EOF'
+# DaVinci Resolve aloop default-sink exclusion - managed by install-davinci-resolve.sh
+# Without this, wireplumber promotes aloop to default whenever Resolve makes
+# it RUNNING and the loopback bridge sends audio back into aloop. Setting
+# both dont-fallback and disable-fallback covers minor key renames in the
+# wireplumber 0.5.x series.
+monitor.alsa.rules = [
+ {
+ matches = [
+ { node.name = "alsa_output.platform-snd_aloop.0.analog-stereo" }
+ { node.name = "alsa_input.platform-snd_aloop.0.analog-stereo" }
+ ]
+ actions = {
+ update-props = {
+ priority.session = 0
+ priority.driver = 0
+ node.dont-fallback = true
+ node.disable-fallback = true
+ }
+ }
+ }
+]
+EOF
+ success "Wrote $wp_file (wireplumber default-sink exclusion)."
+ else
+ info "$wp_file already in place."
+ fi
+
+ # 5. Restart user services so the configs are picked up. wireplumber
+ # first, then pipewire/pipewire-pulse so the alsa rule re-applies
+ # when pipewire republishes aloop nodes.
+ if systemctl --user is-active --quiet pipewire 2>/dev/null; then
+ systemctl --user restart wireplumber pipewire pipewire-pulse 2>/dev/null || true
+ info "Reloaded user wireplumber + PipeWire services."
+ fi
+}
+
configure_user_groups() {
# Davincibox requirement: user must be in 'render' and 'video' groups
# Without these, DaVinci Resolve may hang during rendering or fail to detect GPU
@@ -1453,38 +1681,135 @@ configure_user_groups() {
fi
}
-setup_studio_usb_dongle() {
- # For DaVinci Resolve Studio with USB license dongle
- # Davincibox mentions vendor ID 096e for USB dongle access
- header "Checking Studio USB Dongle Support"
+reset_stale_configs() {
+ # Resolve defaults to GPU Processing Mode = CUDA on Linux. If a previous
+ # launch couldn't find an OpenCL device (e.g. ROCm wasn't installed yet,
+ # or an install was interrupted), Resolve writes a config snapshot and
+ # segfaults with "Unsupported GPU Processing Mode". Subsequent launches
+ # reuse that broken snapshot and crash the same way - even after the
+ # OpenCL stack is fixed. The fix is to delete configs/ and logs/ so
+ # Resolve goes through first-launch onboarding again.
+ #
+ # Project databases under "Resolve Disk Database/" and "Resolve Project
+ # Library/" are NOT touched. Set RESOLVE_RESET_CONFIG=1 to force.
+ header "Checking for stale Resolve configs"
- local udev_rule_file="/etc/udev/rules.d/75-davinci-resolve-dongle.rules"
- local udev_rule='SUBSYSTEM=="usb", ATTR{idVendor}=="096e", MODE="0666"'
+ local resolve_user_dir="${HOME}/.local/share/DaVinciResolve"
+ local prior_crash=0
- # Check if Studio version
- if [[ -f "/opt/resolve/bin/resolve" ]]; then
- # Check if it's Studio by looking for specific files or just offer the option
- if pacman -Qq davinci-resolve-studio &>/dev/null 2>&1 || \
- [[ -f "/opt/resolve/Developer/Scripting/README.txt" ]]; then
- info "DaVinci Resolve Studio detected"
+ # Match any of the known crash signatures. ROCm 7.2 produces several:
+ # 'Unsupported GPU Processing Mode' is the original symptom (no OpenCL
+ # device visible at all). 'OpenCL Context Manager failed to create
+ # context' / 'Failed to create OpenCL context' fire when the device IS
+ # visible but clCreateContext fails - the actual recurrence the v4.1
+ # script missed on fresh installs. Once any of these poisoned configs
+ # land, every subsequent launch reuses them and crashes the same way.
+ local crash_markers='Unsupported GPU Processing Mode|OpenCL Context Manager failed to create context|Failed to create OpenCL context'
+ if [[ -f "${resolve_user_dir}/logs/ResolveDebug.txt" ]] && \
+ grep -qE "${crash_markers}" "${resolve_user_dir}/logs/ResolveDebug.txt" 2>/dev/null; then
+ prior_crash=1
+ local hit
+ hit=$(grep -oE "${crash_markers}" "${resolve_user_dir}/logs/ResolveDebug.txt" 2>/dev/null | head -1)
+ warn "Detected prior crash marker: '${hit}'"
+ fi
- if [[ ! -f "$udev_rule_file" ]]; then
- read -p "Set up USB dongle udev rule for Studio license? [y/N] " -n 1 -r
- echo
- if [[ $REPLY =~ ^[Yy]$ ]]; then
- echo "$udev_rule" | sudo tee "$udev_rule_file" > /dev/null
- sudo udevadm control --reload-rules
- sudo udevadm trigger
- success "USB dongle udev rule installed."
- fi
- else
- info "USB dongle udev rule already exists."
- fi
+ # On a fresh Resolve install (SCAN_RESOLVE_INSTALLED=false), any configs
+ # present can only have been written by a failed launch during this same
+ # install run - there is no real user state to preserve. Wipe them
+ # unconditionally so we never re-read a poisoned snapshot.
+ local fresh_install=0
+ if [[ "${SCAN_RESOLVE_INSTALLED}" != "true" ]]; then
+ fresh_install=1
+ fi
+
+ if (( prior_crash )) || (( fresh_install )) || [[ "${RESOLVE_RESET_CONFIG:-0}" == "1" ]]; then
+ if (( prior_crash )); then
+ info "Resetting stale configs to recover from prior failed launch."
+ elif (( fresh_install )); then
+ info "Fresh Resolve install - clearing any configs from in-install launches."
else
- info "DaVinci Resolve Free detected - USB dongle rule not needed."
+ info "RESOLVE_RESET_CONFIG=1 set - forcing config reset."
fi
+ info "Project databases preserved (Resolve Disk Database, Resolve Project Library)."
+ rm -rf "${resolve_user_dir}/configs" "${resolve_user_dir}/logs" 2>/dev/null || true
+ success "Stale configs cleared. Next launch will run first-launch onboarding."
else
- info "DaVinci Resolve not yet installed - skipping USB dongle setup."
+ info "No stale config markers found."
+ fi
+}
+
+verify_opencl() {
+ # Sanity-check that an AMD OpenCL platform is visible after install.
+ # Resolve crashes on first launch with 'Unsupported GPU Processing Mode'
+ # if it can't see ANY OpenCL device, so this is the most useful single
+ # check we can do without launching Resolve.
+ header "OpenCL Sanity Check"
+
+ if ! command -v clinfo &>/dev/null; then
+ warn "clinfo not installed - cannot verify OpenCL visibility."
+ return
+ fi
+
+ local platforms
+ platforms=$(clinfo -l 2>/dev/null || true)
+
+ if echo "$platforms" | grep -qiE "AMD|gfx|Radeon"; then
+ success "AMD OpenCL platform visible to clinfo:"
+ echo "$platforms" | head -10
+ else
+ warn "No AMD OpenCL platform detected. Resolve will crash with 'Unsupported GPU Processing Mode'."
+ warn "Run: clinfo -l (and check rocminfo for ROCm device detection)"
+ warn "Verify ICD vendor file: ls /etc/OpenCL/vendors/ (should include amdocl64.icd)"
+ fi
+
+ # Pinned-stack health check
+ if [[ "$OPENCL_PROVIDER" == "rocm-pinned-7.1.1" ]]; then
+ local stack_ok=1
+ for pkg in rocm-core rocm-device-libs rocm-llvm rocm-opencl-runtime comgr; do
+ local ver
+ ver=$(pacman -Q "$pkg" 2>/dev/null | awk '{print $2}')
+ if [[ -z "$ver" ]]; then
+ warn "Missing pinned package: $pkg"
+ stack_ok=0
+ elif [[ ! "$ver" =~ 7\.1\.1 ]]; then
+ warn "$pkg is at $ver but expected 7.1.1 - pin may have been overridden!"
+ stack_ok=0
+ fi
+ done
+ local spirv_ver
+ spirv_ver=$(pacman -Q spirv-llvm-translator 2>/dev/null | awk '{print $2}')
+ if [[ -n "$spirv_ver" && ! "$spirv_ver" =~ 21\.1\.3 ]]; then
+ warn "spirv-llvm-translator is at $spirv_ver but expected 21.1.3"
+ stack_ok=0
+ fi
+ if [[ "$stack_ok" == 1 ]]; then
+ success "ROCm 7.1.1 pinned stack confirmed at correct versions."
+ else
+ warn "ROCm pinned stack drift detected - re-run install_rocm_pinned to repair."
+ fi
+
+ # IgnorePkg sanity
+ if grep -qE "^IgnorePkg.*rocm-core" /etc/pacman.conf; then
+ success "IgnorePkg pin is in place in /etc/pacman.conf [options]."
+ else
+ warn "IgnorePkg pin missing - next 'pacman -Syu' will break Resolve."
+ warn "Re-run install_rocm_pinned to fix."
+ fi
+ fi
+}
+
+cleanup_stale_extracts() {
+ # Previous failed runs may leave .resolve-extract-XXXXXX dirs (5-10 GB each)
+ # in ~/Downloads. Always clean these at the start.
+ local downloads_dir="$HOME/Downloads"
+ local stale=()
+ while IFS= read -r -d '' d; do
+ stale+=("$d")
+ done < <(find "$downloads_dir" -maxdepth 1 -type d -name '.resolve-extract-*' -print0 2>/dev/null)
+
+ if [[ ${#stale[@]} -gt 0 ]]; then
+ info "Cleaning ${#stale[@]} stale extraction dir(s) in ~/Downloads..."
+ rm -rf "${stale[@]}" 2>/dev/null || true
fi
}
@@ -1494,84 +1819,124 @@ create_launcher() {
local launcher_dir="$HOME/.local/bin"
mkdir -p "$launcher_dir"
- # Check for switcherooctl (davincibox method for hybrid GPU)
- local has_switcheroo=false
- if command -v switcherooctl &>/dev/null && systemctl is-active --quiet switcheroo-control 2>/dev/null; then
- has_switcheroo=true
- fi
-
- # Determine GPU launch method for hybrid systems
+ # GPU lock: whenever an AMD discrete GPU is present, pin OpenGL/Vulkan
+ # to that exact PCI bus address. This is unconditional - not gated on
+ # SCAN_IS_HYBRID, not gated on switcherooctl - because:
+ #
+ # - DRI_PRIME=1 is index-based and unsafe: it means "the OTHER card
+ # relative to Mesa's default", which on systems where the monitor
+ # is plugged into the AMD card is already AMD. =1 then FLIPS OpenGL
+ # to the iGPU, OpenCL stays on AMD via ROCR_VISIBLE_DEVICES, and
+ # CL/GL interop (clCreateContext with CL_GL_CONTEXT_KHR) fails -
+ # Resolve hangs on the Color page.
+ # - switcherooctl internally also uses DRI_PRIME=1, so it inherits
+ # the same bug. Skipping it avoids a needless layer.
+ # - On a single-GPU AMD box the pin is a no-op (correct card by
+ # default) but harmless, so we always emit it for safety.
+ #
+ # The explicit pci-DDDD_BB_DD_F tag pins by bus address and always
+ # lands on the real AMD card regardless of enumeration order, monitor
+ # routing, or compositor GBM device selection.
local gpu_launch_method=""
local prime_config=""
- if [[ "$SCAN_IS_HYBRID" == true ]]; then
- if [[ "$has_switcheroo" == true ]]; then
- # Davincibox method: use switcherooctl for GPU selection
- gpu_launch_method="switcheroo"
- info "Using switcherooctl for GPU selection (davincibox method)"
- elif [[ "$SCAN_HAS_AMD_DGPU" == true ]]; then
- # Fallback: AMD discrete GPU - use DRI_PRIME
+ if [[ "$SCAN_HAS_AMD_DGPU" == true ]]; then
+ local amd_pci_tag=""
+ for i in "${!SCAN_GPU_VENDORS[@]}"; do
+ if [[ "${SCAN_GPU_VENDORS[$i]}" == "AMD" && "${SCAN_GPU_TYPES[$i]}" == "discrete" ]]; then
+ amd_pci_tag="pci-0000_${SCAN_GPU_PCI_IDS[$i]//[:.]/_}"
+ break
+ fi
+ done
+ if [[ -n "$amd_pci_tag" ]]; then
gpu_launch_method="dri_prime"
- prime_config='
-# Hybrid GPU: Force discrete AMD GPU
-export DRI_PRIME=1'
- elif [[ "$SCAN_HAS_NVIDIA_DGPU" == true ]]; then
- # Fallback: NVIDIA discrete GPU - use NVIDIA offload
- gpu_launch_method="nvidia_prime"
- prime_config='
+ prime_config="
+# Lock GPU to the discrete AMD card by PCI bus address. See create_launcher()
+# in install-davinci-resolve.sh for why this is unconditional and why
+# DRI_PRIME=1 / switcherooctl are deliberately not used.
+export DRI_PRIME=${amd_pci_tag}
+export MESA_VK_DEVICE_SELECT_FORCE_DEFAULT_DEVICE=1
+export MESA_VK_DEVICE_SELECT=${amd_pci_tag}"
+ else
+ warn "AMD discrete GPU detected but PCI ID missing - falling back to no DRI_PRIME pin."
+ fi
+ elif [[ "$SCAN_IS_HYBRID" == true && "$SCAN_HAS_NVIDIA_DGPU" == true ]]; then
+ # Hybrid + NVIDIA discrete (no AMD discrete): use NVIDIA offload
+ gpu_launch_method="nvidia_prime"
+ prime_config='
# Hybrid GPU: Force discrete NVIDIA GPU
export __NV_PRIME_RENDER_OFFLOAD=1
export __GLX_VENDOR_LIBRARY_NAME=nvidia
export __VK_LAYER_NV_optimus=NVIDIA_only'
- fi
fi
- # ROCm environment configuration
+ # ROCm environment configuration.
+ # For rocm-pinned-7.1.1 (the working stack), ALWAYS export
+ # HSA_OVERRIDE_GFX_VERSION (matched to the detected gfx target) and
+ # ROCR_VISIBLE_DEVICES=0. These were empirically required to make
+ # Resolve's clCreateContext succeed on RDNA4 + ROCm 7.1.1 even though
+ # gfx1200 is "natively supported".
local rocm_config=""
- if [[ "$OPENCL_PROVIDER" == "rocm-full" ]]; then
- rocm_config='
-# ROCm environment (full stack from official Arch repos)
-export ROCM_PATH=/opt/rocm
-export PATH="$ROCM_PATH/bin:$PATH"
-export LD_LIBRARY_PATH="$ROCM_PATH/lib:$ROCM_PATH/lib64:$LD_LIBRARY_PATH"
+ if [[ "$OPENCL_PROVIDER" == "rocm-pinned-7.1.1" || "$OPENCL_PROVIDER" == "rocm-full" ]]; then
+ # Choose HSA value:
+ # - if scan detected a card needing spoof override, use that
+ # - else if we know the gfx target, use the matching native value
+ # - else leave unset (let ROCm autodetect)
+ local hsa_value="${SCAN_HSA_OVERRIDE_VALUE}"
+ if [[ -z "$hsa_value" && -n "$SCAN_GFX_TARGET" ]]; then
+ case "$SCAN_GFX_TARGET" in
+ gfx1201) hsa_value="12.0.1" ;;
+ gfx1200) hsa_value="12.0.0" ;;
+ gfx1101) hsa_value="11.0.1" ;;
+ gfx1100) hsa_value="11.0.0" ;;
+ gfx1030) hsa_value="10.3.0" ;;
+ esac
+ fi
-# Enable RDNA4 support (gfx1201)
-export HSA_OVERRIDE_GFX_VERSION=11.0.1
+ local hsa_section=""
+ if [[ -n "$hsa_value" ]]; then
+ hsa_section="
+# Detected ${SCAN_GFX_TARGET}. Setting HSA_OVERRIDE_GFX_VERSION explicitly
+# (required for Resolve to succeed at clCreateContext on AMD even though
+# this target is natively supported by ROCm).
+export HSA_OVERRIDE_GFX_VERSION=${hsa_value}
+# Pin Resolve to the discrete AMD GPU (defensive)
+export ROCR_VISIBLE_DEVICES=0"
+ else
+ hsa_section='
+# Could not auto-detect gfx target. Uncomment one of the lines below:
+# export HSA_OVERRIDE_GFX_VERSION=12.0.1 # RX 9070 / 9070 XT (Navi 48, gfx1201)
+# export HSA_OVERRIDE_GFX_VERSION=12.0.0 # RX 9060 / 9060 XT (Navi 44, gfx1200)
+# export HSA_OVERRIDE_GFX_VERSION=11.0.1 # RX 7700/7800 (Navi 32, gfx1101)
+# export HSA_OVERRIDE_GFX_VERSION=11.0.0 # RX 7900 (Navi 31, gfx1100) / RX 7600 (Navi 33, gfx1102)
+# export HSA_OVERRIDE_GFX_VERSION=10.3.0 # RX 6800/6900 / RX 6600/6700 (RDNA2)
+# export ROCR_VISIBLE_DEVICES=0'
+ fi
+
+ rocm_config="
+# ROCm environment
+export ROCM_PATH=/opt/rocm
+export PATH=\"\$ROCM_PATH/bin:\$PATH\"
+export LD_LIBRARY_PATH=\"\$ROCM_PATH/lib:\$ROCM_PATH/lib64:\$LD_LIBRARY_PATH\"
+${hsa_section}
# ROCm OpenCL configuration
-export OCL_ICD_VENDORS=/etc/OpenCL/vendors'
+export OCL_ICD_VENDORS=/etc/OpenCL/vendors"
fi
- # Create main launcher based on GPU method
- if [[ "$gpu_launch_method" == "switcheroo" ]]; then
- # Davincibox-style launcher using switcherooctl
- cat > "$launcher_dir/davinci-resolve" << EOF
-#!/bin/bash
-# DaVinci Resolve Launcher with workarounds
-# Generated by install script on $(date)
-# OpenCL Provider: $OPENCL_PROVIDER
-# GPU Selection: switcherooctl (davincibox method)
-# Fixes applied: patchelf (davincibox method)
-
-# Qt configuration for XWayland
-export QT_QPA_PLATFORM=xcb
-export QT_AUTO_SCREEN_SCALE_FACTOR=1
-${rocm_config}
-
-# Increase file descriptor limit for large projects
-ulimit -n 65535 2>/dev/null
-
-# Use switcherooctl for discrete GPU selection (davincibox method)
-exec switcherooctl launch /opt/resolve/bin/resolve "\$@"
-EOF
- else
- # Standard launcher with DRI_PRIME/NVIDIA offload
- cat > "$launcher_dir/davinci-resolve" << EOF
+ # Create main launcher. AMD-discrete pin (prime_config) is unconditional
+ # when an AMD dGPU is present, so there is only one launcher template.
+ cat > "$launcher_dir/davinci-resolve" << EOF
#!/bin/bash
# DaVinci Resolve Launcher with workarounds
# Generated by install script on $(date)
# OpenCL Provider: $OPENCL_PROVIDER
# Fixes applied: patchelf (davincibox method)
+# Clear stale single-instance Qt lockfiles (left behind by crashes/SIGKILL)
+for lockfile in /tmp/qtsingleapp-DaVinci*lockfile; do
+ [[ -f "\$lockfile" ]] && rm -f "\$lockfile" 2>/dev/null || true
+done
+
# Qt configuration for XWayland
export QT_QPA_PLATFORM=xcb
export QT_AUTO_SCREEN_SCALE_FACTOR=1
@@ -1583,7 +1948,6 @@ ulimit -n 65535 2>/dev/null
exec /opt/resolve/bin/resolve "\$@"
EOF
- fi
chmod +x "$launcher_dir/davinci-resolve"
@@ -1625,32 +1989,49 @@ EOF
chmod +x "$launcher_dir/davinci-resolve-igpu"
info "Created alternate launcher: davinci-resolve-igpu (uses integrated GPU)"
fi
-
+
# Update PATH in shell configs
for rcfile in ~/.bashrc ~/.zshrc; do
if [[ -f "$rcfile" ]] && ! grep -q 'HOME/.local/bin' "$rcfile"; then
echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$rcfile"
fi
done
-
- # Create desktop entry
- mkdir -p "$HOME/.local/share/applications"
-
- # Determine Exec line based on hybrid status
- local exec_line="$HOME/.local/bin/davinci-resolve %U"
-
- cat > "$HOME/.local/share/applications/davinci-resolve.desktop" << EOF
-[Desktop Entry]
-Version=1.0
-Type=Application
-Name=DaVinci Resolve
-Comment=Professional video editing
-Exec=$exec_line
-Icon=DV_Resolve
-Terminal=false
-Categories=AudioVideo;Video;
-StartupWMClass=resolve
-EOF
+
+ # Patch the Resolve-bundled system .desktop files to invoke our wrapper
+ # instead of the bare /opt/resolve/bin/resolve. The bare binary skips Qt
+ # lockfile cleanup, DRI_PRIME pinning, HSA_OVERRIDE, etc. This is the
+ # difference between "app-menu launch silently does nothing" and
+ # "Resolve actually starts".
+ #
+ # We deliberately DO NOT also create ~/.local/share/applications/davinci-resolve.desktop
+ # - the basenames differ from the system entry (davinci-resolve.desktop vs
+ # DaVinciResolve.desktop), so XDG would not shadow it and walker / app
+ # menus would show TWO "DaVinci Resolve" entries. One patched system
+ # entry is sufficient.
+ local wrapper="$HOME/.local/bin/davinci-resolve"
+ for sysdesktop in \
+ /usr/share/applications/DaVinciResolve.desktop \
+ /usr/share/applications/DaVinciResolveCaptureLogs.desktop; do
+ if [[ -f "$sysdesktop" ]]; then
+ sudo sed -i "s|^Exec=.*|Exec=$wrapper %U|" "$sysdesktop"
+ fi
+ done
+
+ # Remove any user-level davinci-resolve.desktop left over from older
+ # script runs (would duplicate the system entry in walker).
+ rm -f "$HOME/.local/share/applications/davinci-resolve.desktop" 2>/dev/null || true
+
+ sudo update-desktop-database >/dev/null 2>&1 || true
+ update-desktop-database "$HOME/.local/share/applications" >/dev/null 2>&1 || true
+
+ # System-wide convenience symlink so `davinci-resolve` works from any
+ # shell even when ~/.local/bin isn't on PATH (e.g. cron, ssh).
+ if [[ ! -e /usr/bin/davinci-resolve ]]; then
+ echo -e "#!/usr/bin/env bash\nexec $wrapper \"\$@\"" | \
+ sudo tee /usr/bin/davinci-resolve >/dev/null
+ sudo chmod +x /usr/bin/davinci-resolve
+ info "Created /usr/bin/davinci-resolve symlink"
+ fi
success "Launcher created."
@@ -1661,15 +2042,12 @@ EOF
if [[ "$SCAN_IS_HYBRID" == true ]]; then
echo " davinci-resolve-igpu - Force integrated GPU"
- echo ""
- info "Hybrid GPU detected - launcher configured to use discrete GPU"
- if [[ "$gpu_launch_method" == "switcheroo" ]]; then
- echo " Using: switcherooctl launch (davincibox method)"
- elif [[ "$SCAN_HAS_AMD_DGPU" == true ]]; then
- echo " Using: DRI_PRIME=1 (AMD discrete)"
- elif [[ "$SCAN_HAS_NVIDIA_DGPU" == true ]]; then
- echo " Using: __NV_PRIME_RENDER_OFFLOAD=1 (NVIDIA discrete)"
- fi
+ fi
+ echo ""
+ if [[ "$SCAN_HAS_AMD_DGPU" == true ]]; then
+ info "Launcher locked to AMD discrete GPU via PCI tag (DRI_PRIME=${amd_pci_tag:-})"
+ elif [[ "$SCAN_IS_HYBRID" == true && "$SCAN_HAS_NVIDIA_DGPU" == true ]]; then
+ info "Hybrid GPU detected - launcher uses NVIDIA discrete via __NV_PRIME_RENDER_OFFLOAD"
fi
echo ""
@@ -1682,50 +2060,59 @@ configure_hyprland() {
info "Hyprland not installed. Skipping configuration."
return
fi
-
+
header "Configuring Hyprland"
-
+
local hypr_conf="$HOME/.config/hypr/hyprland.conf"
-
+
if [[ ! -f "$hypr_conf" ]]; then
warn "Hyprland config not found at $hypr_conf"
- echo "Add these rules manually:"
+ echo "Add these rules manually (Hyprland 0.53+ syntax):"
echo ""
cat << 'EOF'
-windowrulev2 = tag +drpopup, class:^(resolve)$, floating:1
-windowrulev2 = stayfocused, tag:drpopup
-windowrulev2 = noborder, tag:drpopup
-windowrulev2 = opaque, tag:drpopup
+# Tag every floating Resolve window for easy targeting of the cosmetic
+# tweaks below. Do NOT add `stay_focused on` here - it locks focus inside
+# modal dialogs (Project Settings, Preferences, Render) so clicks on the
+# main window do nothing, which feels like a trapped cursor.
+windowrule = tag +drpopup, match:class ^(resolve)$, match:float 1
+windowrule = border_size 0, match:tag drpopup
+windowrule = no_shadow on, match:tag drpopup
+windowrule = rounding 0, match:tag drpopup
+windowrule = opacity 1, match:tag drpopup
EOF
return
fi
-
+
if grep -q "drpopup.*resolve\|tag +drpopup" "$hypr_conf" 2>/dev/null; then
info "Hyprland rules already configured."
return
fi
-
+
cp "$hypr_conf" "$hypr_conf.backup.$(date +%Y%m%d%H%M%S)"
-
+
+ # Hyprland 0.53+ syntax (windowrulev2 was removed). Verified against
+ # Omarchy's own default windowrules + Hyprland 0.54.3 binary symbols.
cat >> "$hypr_conf" << 'EOF'
-# DaVinci Resolve - Fix floating dialogs
-windowrulev2 = tag +drpopup, class:^(resolve)$, floating:1
-windowrulev2 = stayfocused, tag:drpopup
-windowrulev2 = bordersize 0, tag:drpopup
-windowrulev2 = noborder, tag:drpopup
-windowrulev2 = noshadow, tag:drpopup
-windowrulev2 = rounding 0, tag:drpopup
-windowrulev2 = opaque, tag:drpopup
+# DaVinci Resolve - Fix floating dialogs (Hyprland 0.53+ syntax)
+# Tag every floating Resolve window for easy targeting of the cosmetic
+# tweaks below. Do NOT add `stay_focused on` here - it locks focus inside
+# modal dialogs (Project Settings, Preferences, Render) so clicks on the
+# main window do nothing, which feels like a trapped cursor.
+windowrule = tag +drpopup, match:class ^(resolve)$, match:float 1
+windowrule = border_size 0, match:tag drpopup
+windowrule = no_shadow on, match:tag drpopup
+windowrule = rounding 0, match:tag drpopup
+windowrule = opacity 1, match:tag drpopup
EOF
success "Hyprland rules added."
- info "Reload with: hyprctl reload"
+ info "Reload with: hyprctl reload && hyprctl configerrors"
}
create_conversion_script() {
header "Creating Media Conversion Helper"
-
+
cat > "$HOME/.local/bin/resolve-convert" << 'EOF'
#!/bin/bash
# Convert media to DNxHR for DaVinci Resolve Free (Linux)
@@ -1753,20 +2140,20 @@ EOF
install_diagnostics() {
header "Installing Diagnostics"
-
+
local checker_dir="$HOME/.local/share/davinci-resolve-checker"
-
+
$SCAN_AUR_HELPER -S --needed --noconfirm python-pylspci 2>/dev/null || true
-
+
if [[ -d "$checker_dir" ]]; then
cd "$checker_dir" && git pull --quiet
else
git clone --quiet https://github.com/Ashark/davinci-resolve-checker.git "$checker_dir"
fi
-
+
ln -sf "$checker_dir/davinci-resolve-checker.py" "$HOME/.local/bin/davinci-resolve-checker"
chmod +x "$checker_dir/davinci-resolve-checker.py"
-
+
success "Installed: davinci-resolve-checker"
}
@@ -1779,33 +2166,57 @@ print_summary() {
echo " Launch: davinci-resolve"
echo ""
echo " OpenCL Provider: $OPENCL_PROVIDER"
- echo " Fixes applied: patchelf (davincibox method), OpenCL decoder disable"
- echo ""
- if [[ "$OPENCL_PROVIDER" == "rocm-full" ]]; then
- echo " ROCm tools:"
- echo " rocminfo # Show ROCm GPU info"
- echo " rocm-smi # ROCm System Management Interface"
- echo " clinfo --list # Check OpenCL platforms"
- else
- echo " Troubleshooting:"
- echo " clinfo --list # Check OpenCL"
+ echo " Install method: NVIDIA-mirrored (manual extract + RPATH patch to /opt/resolve)"
+ echo " Fixes applied: glib symlink replace, RPATH patching, OpenCL decoder disable,"
+ echo " audio backend (DeckLink->ALSA), snd-aloop, TLS cert symlink,"
+ echo " Qt lockfile cleanup, libcrypt.so.1 fallback"
+ if [[ "$OPENCL_PROVIDER" == "rocm-pinned-7.1.1" ]]; then
+ echo " + ROCm 7.1.1 pinned from Arch Linux Archive"
+ echo " + IgnorePkg in /etc/pacman.conf [options]"
+ echo " + HSA_OVERRIDE_GFX_VERSION + ROCR_VISIBLE_DEVICES baked into launcher"
fi
+ echo ""
+ echo " Env vars (set before re-running this script):"
+ echo " RESOLVE_NO_ALOOP=1 Skip snd-aloop setup (you have a real audio interface)"
+ echo " RESOLVE_RESET_CONFIG=1 Force-wipe ~/.local/share/DaVinciResolve/{configs,logs}"
+ echo " (use after fixing OpenCL stack to clear crash snapshots)"
+ echo ""
+ if [[ "$OPENCL_PROVIDER" == "rocm-pinned-7.1.1" ]]; then
+ echo " IMPORTANT - ROCm 7.1.1 is PINNED:"
+ echo " ROCm 7.2.x breaks DaVinci Resolve (https://github.com/ROCm/ROCm/issues/5982)"
+ echo " These packages will NOT update on 'pacman -Syu':"
+ echo " rocm-core rocm-device-libs rocm-llvm rocm-opencl-runtime"
+ echo " comgr spirv-llvm-translator"
+ echo " When ROCm 7.3+ ships with the fix, lift the pin:"
+ echo " sudo sed -i '/^IgnorePkg.*rocm-/d' /etc/pacman.conf"
+ echo " sudo pacman -Syu"
+ echo ""
+ fi
+ echo " ROCm/diagnostic tools:"
+ echo " rocminfo # Show ROCm GPU info (Name: + Marketing Name)"
+ echo " rocm-smi # ROCm System Management Interface"
+ echo " clinfo -l # Check OpenCL platforms"
echo " davinci-resolve-checker # Diagnose Resolve issues"
echo ""
echo " Free version codec limitation (Linux):"
echo " No H.264/H.265/MP4 - convert with: resolve-convert video.mp4"
echo ""
- echo " After Resolve updates, re-run this script or manually:"
- echo " # Re-apply patchelf fix to new binaries"
- echo " for bin in /opt/resolve/bin/*; do"
- echo " sudo patchelf --add-needed libglib-2.0.so.0 \"\$bin\" 2>/dev/null"
- echo " done"
+ echo " To upgrade Resolve: download new ZIP to ~/Downloads, re-run this script."
+ echo " To uninstall:"
+ echo " sudo rm -rf /opt/resolve"
+ echo " sudo rm -f /usr/share/applications/{DaVinciResolve,DaVinciControlPanelsSetup,blackmagicraw-*}.desktop"
+ echo " sudo rm -f /usr/lib/udev/rules.d/{99-BlackmagicDevices,99-ResolveKeyboardHID,99-DavinciPanel}.rules"
+ echo " sudo sed -i '/^IgnorePkg.*rocm-/d' /etc/pacman.conf # lift the pin"
echo ""
- if [[ "$SCAN_IS_RDNA4" == true ]]; then
- echo " RDNA4 Note:"
- echo " If Resolve doesn't detect GPU, try adjusting HSA_OVERRIDE_GFX_VERSION"
- echo " in ~/.local/bin/davinci-resolve (currently set to 11.0.1)"
- echo " Common values: 11.0.0 (gfx1100), 11.0.1 (gfx1201)"
+ if [[ -n "$SCAN_GFX_TARGET" ]]; then
+ echo " GPU Detection:"
+ echo " Detected $SCAN_GFX_TARGET. Launcher pre-configured with:"
+ echo " HSA_OVERRIDE_GFX_VERSION (matched to your gfx target)"
+ echo " ROCR_VISIBLE_DEVICES=0"
+ echo " These were empirically required to make Resolve clCreateContext"
+ echo " succeed on AMD even though gfx1100+ targets are 'natively supported'."
+ echo ""
+ echo " Verify GPU detection: rocminfo | grep -E 'Name:|gfx'"
echo ""
fi
echo "============================================================"
@@ -1818,9 +2229,10 @@ print_summary() {
main() {
echo ""
echo "============================================================"
- echo " DaVinci Resolve Installer v3.0"
- echo " Arch Linux + AMD GPU (RDNA4) + Hyprland"
- echo " With Davincibox-style fixes (patchelf, decoder disable)"
+ echo " DaVinci Resolve Installer v4.1"
+ echo " Arch Linux + AMD (RDNA2/3/4) + Hyprland"
+ echo " NVIDIA-mirrored install path (extract + RPATH to /opt/resolve)"
+ echo " ROCm 7.1.1 pinned (working stack for Resolve on AMD, May 2026)"
echo "============================================================"
echo ""
@@ -1849,21 +2261,52 @@ main() {
echo
[[ $REPLY =~ ^[Nn]$ ]] && exit 0
+ # Full system upgrade first - Arch is a rolling distro and partial upgrades
+ # (pacman -Sy without -u) are unsupported and can break the system.
+ # This also ensures we get the latest ROCm.
+ header "System Update"
+ info "Arch is a rolling-release distro - a full system upgrade is recommended"
+ info "before installing new packages, to avoid partial-upgrade breakage and"
+ info "to pull the latest ROCm release."
+ echo ""
+ read -p "Run 'sudo pacman -Syu' now? [Y/n] " -n 1 -r
+ echo
+ if [[ ! $REPLY =~ ^[Nn]$ ]]; then
+ sudo pacman -Syu --noconfirm
+ # Refresh the cached package list since the upgrade may have changed it
+ scan_installed_packages
+ success "System updated."
+ else
+ warn "Skipping system upgrade - proceed at your own risk."
+ warn "If pacman complains about stale databases, re-run after 'sudo pacman -Syu'."
+ fi
+
# Configure user groups for GPU access
configure_user_groups
+ # Clean up any leftover extraction dirs from prior failed runs
+ cleanup_stale_extracts
+
# Install
install_pacman_packages
install_aur_packages
+ install_rocm_pinned # downloads ROCm 7.1.1 from ALA + pins it
install_davinci_resolve
- apply_patchelf_fix
disable_opencl_decoders
- setup_studio_usb_dongle
+ setup_tls_symlink
+ patch_audio_backend
+ setup_snd_aloop
create_launcher
configure_hyprland
create_conversion_script
install_diagnostics
+ # Reset stale Resolve user configs if a prior crash marker exists
+ reset_stale_configs
+
+ # Final sanity check
+ verify_opencl
+
print_summary
}