Initial commit — DaVinci Resolve installer for Intel Arc on Omarchy

This commit is contained in:
nosignal 2026-05-01 22:29:14 +01:00
commit 2af027c9fe
4 changed files with 1030 additions and 0 deletions

9
.gitignore vendored Normal file
View file

@ -0,0 +1,9 @@
# Editor / OS junk
.DS_Store
*.swp
*~
# Local Resolve test artefacts
/squashfs-root/
DaVinci_Resolve_*_Linux.run
DaVinci_Resolve_*_Linux.zip

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Gavin Nugent / NO SIGNAL
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

354
README.md Normal file
View file

@ -0,0 +1,354 @@
# DaVinci Resolve - Intel Arc Omarchy
Install [DaVinci Resolve](https://www.blackmagicdesign.com/products/davinciresolve) on [Omarchy](https://omarchy.com) (Arch Linux + Hyprland) with **Intel Arc** GPU support — Alchemist (Arc Axxx, A770), Battlemage (B580/B570), and Panther Lake Xe3-LPG iGPUs (Arc B360/B370/B380/B390 in Core Ultra 300).
Adapted from the NVIDIA variant. Handles ABI-safe library replacement, RPATH patching, the OpenCL/Level Zero stack, GPU pinning by PCI BDF, the DeckLink → ALSA audio default, and the `snd-aloop` render-blocker fix.
> **Support caveat**
> Blackmagic does **not** officially support Intel GPUs on Linux. With `intel-compute-runtime` installed the Arc shows up as an OpenCL device and editing/playback/transcode generally work, but Neural Engine, Fairlight FX, noise reduction, and some effects may fall back to CPU or fail. Treat this as community/experimental — not a supported configuration.
## Requirements
- **OS**: [Omarchy](https://omarchy.com) (Arch Linux + Hyprland)
- **GPU**: Intel Arc on the `xe` driver
- Alchemist Xe-HPG dGPU (Arc Axxx, e.g. A770)
- Battlemage Xe2 dGPU (Arc B580/B570, late 2024)
- Panther Lake Xe3-LPG iGPU (Core Ultra 300, Jan 2026)
- Older UHD/Iris on `i915` is detected but not preferred for pinning when an `xe` device is present
- **Kernel**: 6.12+ (Xe driver). 6.19+ recommended for stable Battlemage support
- **Audio stack**: PipeWire + Wireplumber (Omarchy default)
- **Disk space**: ~10 GiB free in `~/Downloads` for extraction (temporary)
- **DaVinci Resolve ZIP**: downloaded from Blackmagic's website
## Quick Start
1. **Download DaVinci Resolve** from [blackmagicdesign.com](https://www.blackmagicdesign.com/products/davinciresolve)
- Choose "DaVinci Resolve" (free) or "DaVinci Resolve Studio" (paid)
- Select **Linux** and download the ZIP
- Save it to `~/Downloads/`
2. **Run the installer**:
```bash
git clone https://git.no-signal.uk/nosignal/DaVinci-Resolve-Intel-Arc-Omarchy.git
cd DaVinci-Resolve-Intel-Arc-Omarchy
chmod +x install-davinci-resolve-intel-arc.sh
./install-davinci-resolve-intel-arc.sh
```
3. **Launch Resolve** from your app menu, or run `resolve-intel-arc`.
## What It Does
### 1. Preflight checks
- Verifies kernel ≥ 6.12 (warns and continues otherwise)
- Greps `lspci` for Intel Arc GPUs
- Picks the newest `DaVinci_Resolve*_Linux.zip` in `~/Downloads/` by mtime
- Refuses to start if `~/Downloads/` has under 10 GiB free
### 2. Installs dependencies
**Build/extraction tools:**
| Package | Purpose |
|---------|---------|
| `unzip` | Extract the Resolve ZIP |
| `patchelf` | RPATH patching of all ELF binaries |
| `libarchive` | Archive handling |
| `desktop-file-utils` | App menu integration |
| `file` | Identify ELF binaries for patchelf |
| `gtk-update-icon-cache` | Refresh hicolor icon cache |
**Runtime dependencies (Intel-specific stack on top of the common set):**
| Package | Purpose |
|---------|---------|
| `libxcrypt-compat` | Legacy `libcrypt.so.1` (Arch moved to v2) |
| `ffmpeg4.4` | Older FFmpeg version Resolve links against |
| `glu` | OpenGL Utility Library |
| `fuse2` | AppImage compatibility layer |
| `mesa` | OpenGL stack (Iris driver) |
| `vulkan-intel` | ANV — Vulkan ICD for Intel |
| `intel-media-driver` | iHD VA-API driver (HW H.264/HEVC/AV1 decode/encode) |
| `intel-compute-runtime` | NEO — OpenCL & Level Zero ICD. **What Resolve actually uses for compute.** |
| `level-zero-loader` | Loader for Intel oneAPI Level Zero |
| `ocl-icd` | Generic OpenCL ICD loader (`libOpenCL.so.1`) |
| `clinfo` | Sanity tool — used post-install to confirm OpenCL visibility |
The script aborts if any of `intel-compute-runtime`, `level-zero-loader`, `ocl-icd`, or `clinfo` failed to install — without them Resolve sees no OpenCL device and crashes with **Unsupported GPU Processing Mode** on first launch.
> Note: `gtk2` is **not** installed. Verified via `ldd` that Resolve 21 doesn't link `libgtk-x11-2.0`; the modern UI is fully Qt. The leftover `gtk2` dep in older install scripts came from the era when Resolve had GTK file dialogs.
### 3. Extracts Resolve
```
ZIP → .run file → squashfs-root (actual application files)
```
Temporary files clean up automatically via an `EXIT` trap.
### 4. ABI-safe library replacement
The same library policy as the NVIDIA variant — these libraries are GPU-agnostic:
| Library | Action | Why |
|---------|--------|-----|
| `libglib-2.0.so` | **Replace** with system | Stable C ABI, safe to swap |
| `libgio-2.0.so` | **Replace** with system | Stable C ABI, safe to swap |
| `libgmodule-2.0.so` | **Replace** with system | Stable C ABI, safe to swap |
| `libc++.so` | **Keep** bundled | C++ ABI mismatch causes crashes |
| `libc++abi.so` | **Keep** bundled | C++ ABI mismatch causes crashes |
### 5. Patches RPATH
Every ELF binary in `/opt/resolve` gets RPATH patched to point at `/opt/resolve/libs/` and the relevant subdirectories (Fusion, BlackmagicRAW, Onboarding, Qt plugins, etc.). Without this, binaries would look for libraries at the original AppImage paths that no longer exist.
### 6. Legacy `libcrypt.so.1` shim
Arch dropped `libcrypt.so.1`. The script ensures `libxcrypt-compat` is present so Resolve's older link continues to resolve.
### 7. Desktop integration
- Installs `.desktop` entries for Resolve, Capture Logs, Control Panels Setup, BlackmagicRAW Player & SpeedTest
- Installs hicolor icons (128/256 px)
- Installs udev rules for Blackmagic capture cards, the Resolve Editor Keyboard, and DaVinci control panels
- Re-points all launchers at the XWayland wrapper (`/usr/local/bin/resolve-intel-arc`)
- Drops a user-level `.desktop` override at `~/.local/share/applications/davinci-resolve-wrapper.desktop` so future system updates don't undo the wrapper
### 8. XWayland wrapper (Intel Arc)
A wrapper script at `/usr/local/bin/resolve-intel-arc`:
- Forces XWayland under Hyprland/Wayland (`QT_QPA_PLATFORM=xcb`)
- Pins `LIBVA_DRIVER_NAME=iHD` for Intel media driver VA-API decode
- Sets `OCL_ICD_VENDORS=/etc/OpenCL/vendors` so the Intel ICD is found
- Clears stale `qtsingleapp-DaVinci*lockfile` files left behind after a crash
- **Pins the GPU by PCI BDF**, not by Level Zero index
#### GPU pinning (BDF-based)
NEO/Level Zero enumerates *every* Intel GPU it supports across both `xe` and `i915` backends, sorted by PCI BDF — but the numeric index is not a reliable function of BDF order. On hybrid Battlemage + iGPU systems, NEO often enumerates the discrete card at index 0 even though its BDF sorts later. The wrapper avoids the indexing trap entirely:
1. Walks `/sys/class/drm/card[0-9]*` and collects every device with vendor `0x8086`
2. **Priority 1**: discrete `xe` device (BDF *not* on bus `00:` — i.e. not an SoC iGPU). This picks Battlemage B580/B570 dGPUs.
3. **Priority 2**: any `xe` device (covers Panther Lake Xe3-LPG iGPU)
4. **Priority 3**: first Intel device (last-resort fallback)
5. Exports the chosen device's BDF as `ZE_AFFINITY_MASK` in `DDDD:BB:DD.F` form (e.g. `0000:03:00.0`) — NEO matches this directly against the device
#### Battlemage OpenCL workaround
Discrete Battlemage Xe2 silicon needs an OpenCL init workaround. The wrapper applies it **only** if `lspci` shows Battlemage **and** the picked BDF is *not* on bus `00:` (so iGPUs are excluded — Intel reuses the "Arc B-series" brand for the Xe3-LPG iGPUs in Panther Lake, and they don't want this debug key):
```bash
export NEOReadDebugKeys=1
export OverrideGpuAddressSpace=48
```
### 9. Audio backend default (DeckLink → ALSA)
Resolve ships with `Local.Audio.Type = DeckLink` in its system-wide config template at `/opt/resolve/share/default-config.dat`. Correct for users with a Blackmagic DeckLink card; aborts on first launch otherwise. The script patches:
- The system template (so future first-launches are correct)
- Any existing user config at `~/.local/share/DaVinciResolve/configs/config.dat`, with a timestamped `.bak.<epoch>` backup
### 10. `snd-aloop` (the actual render-blocker fix)
Resolve's audio engine opens raw ALSA hardware via `snd_pcm_open("hw:%d", ...)` — it never goes through ALSA's plugin layer (`default`/`pulse`/`pipewire`) and it enumerates *every* card under `/dev/snd/controlC[0-32]` looking for a usable PCM. When every real ALSA card is owned/contested by PipeWire's session manager, Resolve loops forever. Symptoms:
- Wireplumber meters "flicker" as Resolve repeatedly opens `controlC*`
- Render sits at "in progress" with growing ETA, no output file
- `ResolveDebug.txt` shows nothing useful
- `strace` shows tens of thousands of `SNDRV_CTL_IOCTL_PCM_INFO` `ENXIO` ioctls per failed render attempt
**The fix**: load the kernel's `snd-aloop` module. PipeWire ignores it (no ACP profile, not auto-acquired), so Resolve can fully own it and the render proceeds. The script:
- `modprobe snd-aloop` for the current session
- Writes `/etc/modules-load.d/snd-aloop.conf` so it autoloads at boot
- Writes a PipeWire loopback bridge at `~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf` so monitor audio routes from the loopback's capture side to the current default sink (without it, Resolve plays back silently — headphone/HDMI sink switching keeps working through the bridge)
- Restarts user PipeWire/Wireplumber so the conf loads immediately
Set `RESOLVE_NO_ALOOP=1` to skip this entirely (useful if you have a dedicated audio interface Resolve already uses cleanly).
### 11. Post-install OpenCL sanity check
Runs `clinfo -l` and reports whether the Intel GPU is visible to the OpenCL stack. If it isn't, Resolve will fall back to CPU.
### 12. Stale-config recovery
Resolve defaults to `GPU Processing Mode = CUDA` on Linux. If a previous launch couldn't find an OpenCL device (e.g. compute runtime was missing the first time), Resolve writes out a config snapshot and segfaults on every subsequent launch — *even after* the OpenCL stack is fixed. The script detects the `Unsupported GPU Processing Mode` marker in `~/.local/share/DaVinciResolve/logs/ResolveDebug.txt` and clears `configs/` and `logs/` to force first-launch onboarding again. **Project databases under `Resolve Disk Database/` and `Resolve Project Library/` are not touched.**
Force a manual reset with `RESOLVE_RESET_CONFIG=1`.
## Files Installed
### Application
| Path | Purpose |
|------|---------|
| `/opt/resolve/` | Main application directory |
| `/opt/resolve/bin/resolve` | Resolve binary |
| `/opt/resolve/libs/` | Bundled libraries (vendor `libc++` kept) |
### Scripts
| Path | Purpose |
|------|---------|
| `/usr/local/bin/resolve-intel-arc` | XWayland wrapper (main launcher) |
| `/usr/bin/davinci-resolve` | Convenience symlink to wrapper |
### Desktop entries
| Path | Purpose |
|------|---------|
| `/usr/share/applications/DaVinciResolve.desktop` | System app menu entry |
| `~/.local/share/applications/davinci-resolve-wrapper.desktop` | User entry (takes priority, survives reinstalls) |
### Icons
| Path | Purpose |
|------|---------|
| `/usr/share/icons/hicolor/128x128/apps/davinci-resolve.png` | App icon |
| `/usr/share/icons/hicolor/256x256/apps/blackmagicraw-player.png` | BMRAW Player icon |
### Hardware support
| Path | Purpose |
|------|---------|
| `/usr/lib/udev/rules.d/99-BlackmagicDevices.rules` | Capture cards |
| `/usr/lib/udev/rules.d/99-ResolveKeyboardHID.rules` | Resolve Editor Keyboard |
| `/usr/lib/udev/rules.d/99-DavinciPanel.rules` | DaVinci control panels |
### Audio
| Path | Purpose |
|------|---------|
| `/etc/modules-load.d/snd-aloop.conf` | Autoload `snd-aloop` at boot |
| `~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf` | Loopback monitor bridge |
## Environment Variables
All optional — set when running the script or the launcher:
| Variable | Effect |
|----------|--------|
| `RESOLVE_FULL_UPGRADE=1` | Run `pacman -Syu` instead of just `-Sy` before installing deps |
| `RESOLVE_NO_ALOOP=1` | Skip the `snd-aloop` setup entirely (use if you have a dedicated audio interface) |
| `RESOLVE_RESET_CONFIG=1` | Force-clear Resolve's `configs/` and `logs/` even if no prior crash is detected |
| `RESOLVE_GPU_BDF=0000:XX:YY.Z` | Manual GPU pinning override (sets `ZE_AFFINITY_MASK`) |
| `RESOLVE_NO_PIN=1` | Disable `ZE_AFFINITY_MASK` pinning — let NEO pick whatever it wants |
Examples:
```bash
# First install on a system that hasn't been pacman-upgraded recently
RESOLVE_FULL_UPGRADE=1 ./install-davinci-resolve-intel-arc.sh
# Skip the audio fix
RESOLVE_NO_ALOOP=1 ./install-davinci-resolve-intel-arc.sh
# Pin to a specific Arc B580 at 04:00.0
RESOLVE_GPU_BDF=0000:04:00.0 resolve-intel-arc
```
## Troubleshooting
### Resolve crashes on launch with "Unsupported GPU Processing Mode"
Either the OpenCL stack isn't visible, or you have a stale config from a previous failed launch.
```bash
# Confirm OpenCL sees the Arc
clinfo -l
# If clinfo lists nothing, check the compute stack
pacman -Q intel-compute-runtime level-zero-loader ocl-icd
# If clinfo is fine but Resolve still crashes, force a config reset
RESOLVE_RESET_CONFIG=1 ./install-davinci-resolve-intel-arc.sh
```
### Render starts but never finishes (no output file, growing ETA)
This is the `snd-aloop` render-blocker. Either you ran with `RESOLVE_NO_ALOOP=1`, or `snd-aloop` failed to load.
```bash
# Confirm the module is loaded
lsmod | grep snd_aloop
# If not, load it manually
sudo modprobe snd-aloop
# And persist it
echo snd-aloop | sudo tee /etc/modules-load.d/snd-aloop.conf
```
### Wrong GPU selected on a hybrid system
Override `ZE_AFFINITY_MASK` directly:
```bash
# Find your Intel GPUs
for d in /sys/class/drm/card[0-9]*; do
vendor=$(cat "$d/device/vendor" 2>/dev/null)
[[ "$vendor" == "0x8086" ]] || continue
echo "$(basename "$(readlink -f "$d/device")") -> $(basename "$d")"
done
# Pin to the right BDF
RESOLVE_GPU_BDF=0000:03:00.0 resolve-intel-arc
```
### Battlemage-specific OpenCL init failures
The wrapper applies `NEOReadDebugKeys=1` + `OverrideGpuAddressSpace=48` automatically when it detects a discrete Battlemage card. If you've manually overridden `RESOLVE_GPU_BDF` to a non-Battlemage BDF, those debug keys aren't set — set them yourself if you actually want them.
### Stale Qt lockfiles after a crash
The wrapper clears `/tmp/qtsingleapp-DaVinci*lockfile` on every launch — but if the wrapper isn't being used (e.g. you ran `/opt/resolve/bin/resolve` directly), clear them manually:
```bash
rm -f /tmp/qtsingleapp-DaVinci*lockfile
```
### Logs
```
~/.local/share/DaVinciResolve/logs/ResolveDebug.txt
```
## Uninstalling
```bash
# Resolve itself
sudo rm -rf /opt/resolve
sudo rm -f /usr/local/bin/resolve-intel-arc /usr/bin/davinci-resolve
# Desktop entries / icons
sudo rm -f /usr/share/applications/DaVinciResolve.desktop \
/usr/share/applications/DaVinciResolveCaptureLogs.desktop \
/usr/share/applications/DaVinciControlPanelsSetup.desktop \
/usr/share/applications/blackmagicraw-player.desktop \
/usr/share/applications/blackmagicraw-speedtest.desktop \
/usr/share/icons/hicolor/128x128/apps/davinci-resolve*.png \
/usr/share/icons/hicolor/256x256/apps/blackmagicraw-*.png
rm -f ~/.local/share/applications/davinci-resolve-wrapper.desktop
# Audio fix (optional — leaving it in place is harmless)
sudo rm -f /etc/modules-load.d/snd-aloop.conf
rm -f ~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf
sudo update-desktop-database 2>/dev/null
sudo gtk-update-icon-cache -f /usr/share/icons/hicolor 2>/dev/null
```
User configs and project databases under `~/.local/share/DaVinciResolve/` are left in place — delete them by hand if you want a fully clean uninstall.
## Related
- [DaVinci-Resolve-Omarchy](https://git.no-signal.uk/nosignal/DaVinci-Resolve-Omarchy) — NVIDIA variant
- [DaVinci-Resolve-AMD-Omarchy](https://git.no-signal.uk/nosignal/DaVinci-Resolve-AMD-Omarchy) — AMD (RDNA 14) variant
- [DaVinci-Resolve-Linux-Mint](https://git.no-signal.uk/nosignal/DaVinci-Resolve-Linux-Mint), [DaVinci-Resolve-PopOS](https://git.no-signal.uk/nosignal/DaVinci-Resolve-PopOS), [DaVinci-Resolve-openSUSE-Tumbleweed](https://git.no-signal.uk/nosignal/DaVinci-Resolve-openSUSE-Tumbleweed) — non-Arch installers
## License
MIT — see [LICENSE](LICENSE).

View file

@ -0,0 +1,646 @@
#!/usr/bin/env bash
# ==============================================================================
# DaVinci Resolve Installer for Omarchy (Arch Linux + Hyprland + Intel Arc)
#
# Adapted from the NVIDIA-Open variant for systems with an Intel Arc GPU
# using the Xe kernel driver. Covers all current Arc-class hardware:
# - Alchemist Xe-HPG dGPU (Arc Axxx, e.g. A770) — xe driver
# - Battlemage Xe2 dGPU (Arc B580/B570, late 2024) — xe driver
# - Panther Lake Xe3-LPG iGPU (Arc B360/B370/B380/B390, — xe driver
# Core Ultra 300 series, launched Jan 2026)
# Older iGPUs (UHD/Iris on Gen 912.5) sit on the i915 driver and are
# also detected; they're left visible to OpenCL but not preferred for
# pinning when an xe device is available.
#
# IMPORTANT — SUPPORT CAVEAT
# Blackmagic does NOT officially support Intel GPUs on Linux. Resolve uses
# OpenCL (or CUDA on NVIDIA) for compute. With intel-compute-runtime
# installed, the Arc shows up as an OpenCL device and basic editing /
# playback / transcode often work, but specific effects, Neural Engine,
# Fairlight FX, and noise reduction may fall back to CPU or fail. Treat
# this as community/experimental — not a supported configuration.
#
# What this script does (same shape as the NVIDIA version):
# 1. Finds the Resolve ZIP in ~/Downloads/
# 2. Installs system + Intel GPU runtime dependencies
# 3. Extracts the ZIP → .run → squashfs-root (AppImage payload)
# 4. Replaces bundled glib/gio/gmodule with system versions (ABI-safe)
# 5. Keeps vendor libc++/libc++abi (removing these breaks Resolve)
# 6. Installs to /opt/resolve with RPATH patching for all ELF binaries
# 7. Ensures legacy libcrypt.so.1 is available (Arch dropped it)
# 8. Installs desktop entries, icons, and udev rules
# 9. Creates an XWayland wrapper script for Hyprland with Intel/OpenCL hints
#
# Prerequisites:
# - Omarchy (Arch Linux) with kernel 6.12+ (Xe driver). 6.19+ recommended
# for stable Battlemage support.
# - DaVinci Resolve Linux ZIP downloaded to ~/Downloads/
# - Internet connection
# ==============================================================================
set -euo pipefail
log(){ echo -e "$*"; }
warn(){ echo -e "⚠️ $*" >&2; }
err(){ echo -e "$*" >&2; exit 1; }
# ==================== Preflight: kernel + GPU ====================
KVER_FULL="$(uname -r)"
KMAJ="${KVER_FULL%%.*}"; KREST="${KVER_FULL#*.}"; KMIN="${KREST%%.*}"
if (( KMAJ < 6 )) || { (( KMAJ == 6 )) && (( KMIN < 12 )); }; then
warn "Kernel ${KVER_FULL} is older than 6.12 — Arc B580 (Battlemage) needs the Xe driver from 6.12+. Continue at your own risk."
else
log "Kernel ${KVER_FULL} OK for Xe driver"
fi
if lspci -nn 2>/dev/null | grep -qiE 'Intel.*(Arc|Battlemage|Alchemist|DG2)'; then
log "Intel Arc GPU detected"
else
warn "No Intel Arc GPU detected via lspci — script will continue but you may not have GPU acceleration"
fi
# ==================== Locate ZIP ====================
ZIP_DIR="${HOME}/Downloads"
shopt -s nullglob
ZIP_FILES=("${ZIP_DIR}"/DaVinci_Resolve*_Linux.zip)
shopt -u nullglob
if [[ ${#ZIP_FILES[@]} -eq 0 ]]; then
err "Put the official DaVinci Resolve Linux ZIP in ${ZIP_DIR}"
fi
# Pick the newest ZIP by mtime without parsing `ls` output.
RESOLVE_ZIP=""
RESOLVE_ZIP_MTIME=0
for _zf in "${ZIP_FILES[@]}"; do
_m=$(stat -c%Y "${_zf}" 2>/dev/null || echo 0)
if (( _m > RESOLVE_ZIP_MTIME )); then
RESOLVE_ZIP_MTIME=${_m}
RESOLVE_ZIP="${_zf}"
fi
done
[[ -n "${RESOLVE_ZIP}" ]] || err "Could not determine newest ZIP file"
log "Using installer ZIP: ${RESOLVE_ZIP}"
# ==================== Package Installation ====================
if [[ "${RESOLVE_FULL_UPGRADE:-0}" == "1" ]]; then
log "Updating system packages (RESOLVE_FULL_UPGRADE=1)..."
sudo pacman -Syu --noconfirm
else
log "Skipping full system upgrade (set RESOLVE_FULL_UPGRADE=1 to enable)"
sudo pacman -Sy --noconfirm
fi
# Build/extraction tools (same as NVIDIA variant)
log "Installing required tools..."
if ! sudo pacman -S --needed --noconfirm unzip patchelf libarchive xdg-user-dirs desktop-file-utils file gtk-update-icon-cache; then
warn "Some optional tools failed to install, continuing anyway..."
fi
# Runtime dependencies — Intel-specific stack added on top of the common set:
# libxcrypt-compat: Provides legacy libcrypt.so.1 (Arch moved to v2)
# ffmpeg4.4: Older FFmpeg version Resolve links against
# glu / gtk2 / fuse2: Same as NVIDIA variant (UI / AppImage compat)
# mesa: OpenGL stack (Iris driver for Intel)
# vulkan-intel: ANV — Vulkan ICD for Intel
# intel-media-driver: iHD VA-API driver (HW decode/encode H.264/HEVC/AV1)
# intel-compute-runtime: NEO — OpenCL (and Level Zero) ICD for Intel GPUs.
# This is what Resolve will actually use for compute.
# level-zero-loader: Loader for Intel oneAPI Level Zero (used by NEO)
# ocl-icd: Generic OpenCL ICD loader (libOpenCL.so.1)
# clinfo: Sanity tool — used at the end to confirm Resolve
# will see the Arc as an OpenCL device.
log "Installing Intel GPU + Resolve runtime dependencies..."
INTEL_RUNTIME_PKGS=(
libxcrypt-compat ffmpeg4.4 glu fuse2
mesa vulkan-intel intel-media-driver
intel-compute-runtime level-zero-loader ocl-icd clinfo
)
# Note: NOT installing gtk2 — verified via ldd that Resolve 21 does not link
# libgtk-x11-2.0. It links libgdk_pixbuf-2.0 (a different package, gdk-pixbuf2,
# already pulled in by virtually any desktop install). The gtk2 dep in older
# Resolve install scripts was a leftover from when Resolve had GTK file
# dialogs — modern Resolve is fully Qt.
if ! sudo pacman -S --needed --noconfirm "${INTEL_RUNTIME_PKGS[@]}"; then
err "pacman failed to install one or more runtime dependencies — re-run with the offending package name to see the error"
fi
# Compute-stack packages are non-negotiable: without them Resolve sees no
# OpenCL device and crashes with "Unsupported GPU Processing Mode" on first
# launch. Verify each is actually present before continuing.
for pkg in intel-compute-runtime level-zero-loader ocl-icd clinfo; do
pacman -Q "$pkg" >/dev/null 2>&1 || err "Required package not installed: ${pkg}"
done
log "Intel compute stack confirmed installed"
# Resolve's built-in extras downloader expects RHEL-style cert path
if [[ ! -e /etc/pki/tls ]]; then
sudo mkdir -p /etc/pki
sudo ln -sf /etc/ssl /etc/pki/tls
fi
# ==================== Extraction ====================
NEEDED_GB=10
FREE_KB=$(df --output=avail -k "${ZIP_DIR}" | tail -n1); FREE_GB=$((FREE_KB/1024/1024))
(( FREE_GB >= NEEDED_GB )) || err "Not enough free space in ${ZIP_DIR}: ${FREE_GB} GiB < ${NEEDED_GB} GiB"
WORKDIR="$(mktemp -d -p "${ZIP_DIR}" .resolve-extract-XXXXXXXX)"
cleanup() {
if [[ -n "${WORKDIR:-}" && -d "${WORKDIR}" ]]; then
log "Cleaning up temporary directory..."
rm -rf "${WORKDIR}" 2>/dev/null || true
fi
}
trap cleanup EXIT
log "Unpacking ZIP to ${WORKDIR}"
unzip -q "${RESOLVE_ZIP}" -d "${WORKDIR}"
RUN_FILE="$(find "${WORKDIR}" -maxdepth 2 -type f -name 'DaVinci_Resolve_*_Linux.run' | head -n1 || true)"
[[ -n "${RUN_FILE}" ]] || err "Could not find the .run installer in the ZIP"
chmod +x "${RUN_FILE}"
EX_DIR="$(dirname "${RUN_FILE}")"
log "Extracting AppImage payload…"
if ! ( cd "${EX_DIR}" && "./$(basename "${RUN_FILE}")" --appimage-extract >/dev/null ); then
err "Failed to extract AppImage payload"
fi
APPDIR="${EX_DIR}/squashfs-root"
[[ -d "${APPDIR}" ]] || err "Extraction failed (no squashfs-root)"
chmod -R u+rwX,go+rX,go-w "${APPDIR}" || warn "Could not normalize all permissions"
[[ -s "${APPDIR}/bin/resolve" ]] || err "resolve binary missing or zero-size"
# ==================== ABI-Safe Library Replacement ====================
# (Identical to NVIDIA variant — these are GPU-agnostic.)
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"
)
for syslib in "${!GLIB_LIBS[@]}"; do
target="${GLIB_LIBS[$syslib]}"
if [[ -e "${syslib}" ]]; then
rm -f "${target}" || true
ln -sf "${syslib}" "${target}" || warn "Failed to symlink ${syslib}"
else
warn "System library ${syslib} not found, keeping bundled version"
fi
done
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
popd >/dev/null
fi
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 ====================
log "Installing Resolve to /opt/resolve…"
sudo rm -rf /opt/resolve
sudo mkdir -p /opt/resolve
if command -v rsync >/dev/null 2>&1; then
sudo rsync -a --delete "${APPDIR}/" /opt/resolve/
else
sudo cp -a "${APPDIR}/." /opt/resolve/
fi
sudo mkdir -p /opt/resolve/.license
log "Applying RPATH with patchelf (this may take a while for large libraries)…"
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" )
RPATH_ABS=""; for p in "${RPATH_DIRS[@]}"; do RPATH_ABS+="/opt/resolve/${p}:"; done; RPATH_ABS+="\$ORIGIN"
if command -v patchelf >/dev/null 2>&1; then
PATCH_COUNT=0
PATCH_FAIL=0
PATCH_SKIP=0
while IFS= read -r -d '' f; do
FILE_INFO="$(file -b "$f" 2>/dev/null)"
if [[ "${FILE_INFO}" =~ ELF.*executable ]] || [[ "${FILE_INFO}" =~ ELF.*shared\ object ]]; then
CURRENT_RPATH="$(patchelf --print-rpath "$f" 2>/dev/null || true)"
if [[ "${CURRENT_RPATH}" == "${RPATH_ABS}" ]]; then
((PATCH_SKIP++)) || true
continue
fi
if sudo patchelf --set-rpath "${RPATH_ABS}" "$f" 2>/dev/null; then
((PATCH_COUNT++)) || true
else
((PATCH_FAIL++)) || true
FILE_SIZE=$(stat -c%s "$f" 2>/dev/null || echo 0)
if (( FILE_SIZE > 33554432 )); then
warn "Failed to patch large file: ${f##/opt/resolve/}"
fi
fi
fi
done < <(find /opt/resolve -type f -print0)
log "Patched RPATH: ${PATCH_COUNT} files (${PATCH_FAIL} failures, ${PATCH_SKIP} already correct)"
else
warn "patchelf not found, skipping RPATH patching"
fi
# Legacy libcrypt fix (same as NVIDIA variant)
sudo pacman -S --needed --noconfirm libxcrypt-compat || true
sudo ldconfig || true
if [[ -e /usr/lib/libcrypt.so.1 ]]; then
sudo ln -sf /usr/lib/libcrypt.so.1 /opt/resolve/libs/libcrypt.so.1
fi
# ==================== Desktop Integration ====================
log "Installing desktop entries and icons..."
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
dest="${DESKTOP_FILES[$src]}"
if [[ -f "${src}" ]]; then
sudo install -D -m 0644 "${src}" "${dest}"
else
warn "Desktop file not found: ${src}"
fi
done
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
dest="${ICON_FILES[$src]}"
if [[ -f "${src}" ]]; then
sudo install -D -m 0644 "${src}" "${dest}"
else
warn "Icon file not found: ${src}"
fi
done
sudo update-desktop-database >/dev/null 2>&1 || true
sudo gtk-update-icon-cache -f /usr/share/icons/hicolor >/dev/null 2>&1 || true
for r in 99-BlackmagicDevices.rules 99-ResolveKeyboardHID.rules 99-DavinciPanel.rules; do
if [[ -f "/opt/resolve/share/etc/udev/rules.d/${r}" ]]; then
sudo install -D -m 0644 "/opt/resolve/share/etc/udev/rules.d/${r}" "/usr/lib/udev/rules.d/${r}"
fi
done
sudo udevadm control --reload-rules && sudo udevadm trigger || true
# ==================== XWayland Wrapper Script (Intel Arc) ====================
#
# Resolve still needs XWayland under Hyprland. Intel-specific bits:
# - OCL_ICD_VENDORS: Force the OpenCL ICD search dir.
# - NEOReadDebugKeys=1 +
# OverrideGpuAddressSpace=48:
# Workaround for OpenCL init failures on
# Battlemage. Applied ONLY if Battlemage is
# detected — Xe3 (Panther Lake) and Alchemist
# don't need it.
# - LIBVA_DRIVER_NAME=iHD: Pin Intel media driver for VA-API decode.
#
# GPU SELECTION (BDF-based, not index-based)
# The wrapper enumerates Intel GPUs at launch and picks one:
# - If a discrete Arc is present (PCI bus != 00, e.g. Battlemage B580 on
# 03:00.0), pick it.
# - Otherwise pick the only xe device available (covers Panther Lake
# laptops with just the Xe3 iGPU, etc.).
# The chosen device's PCI BDF is exported as ZE_AFFINITY_MASK in
# "DDDD:BB:DD.F" form (e.g. "0000:03:00.0"). NEO's numeric Level Zero index
# is NOT a reliable function of BDF order — on hybrid systems NEO often
# enumerates the discrete card at index 0 even though its BDF sorts later —
# so we use the BDF format which NEO matches against the actual device.
# Override with RESOLVE_GPU_BDF=0000:XX:YY.Z if needed; disable pinning
# entirely with RESOLVE_NO_PIN=1.
cat << 'EOF' | sudo tee /usr/local/bin/resolve-intel-arc >/dev/null
#!/usr/bin/env bash
set -euo pipefail
# Clear stale single-instance Qt lockfiles
if [[ -r /tmp ]]; then
for lockfile in /tmp/qtsingleapp-DaVinci*lockfile; do
[[ -f "$lockfile" ]] && rm -f "$lockfile" 2>/dev/null || true
done
fi
# Force XWayland under Hyprland/Wayland
export QT_QPA_PLATFORM=xcb
export QT_AUTO_SCREEN_SCALE_FACTOR=1
# Intel OpenCL / Level Zero (ICD search dir)
export OCL_ICD_VENDORS="${OCL_ICD_VENDORS:-/etc/OpenCL/vendors}"
# Intel VA-API (HW decode)
export LIBVA_DRIVER_NAME=iHD
# --- Detect Intel GPUs and pick the Arc to pin to ---
# NEO/Level Zero enumerates ALL Intel GPUs it supports (both i915 and xe
# backends), sorted by PCI BDF. The picker mirrors that ordering so the
# index we emit matches what ZE_AFFINITY_MASK expects.
#
# Selection priority:
# 1. xe-driven device on a non-SoC PCI bus (a discrete Battlemage like B580)
# 2. any xe-driven device (covers Panther Lake Xe3 iGPU)
# 3. first Intel device found (last-resort fallback)
arc_pick() {
local -a entries=()
local d vendor driver bdf
for d in /sys/class/drm/card[0-9]*; do
# Skip connector subentries like card0-DP-2
[[ "$d" =~ /card[0-9]+$ ]] || continue
[[ -e "$d/device/uevent" ]] || continue
vendor="$(cat "$d/device/vendor" 2>/dev/null || echo)"
[[ "$vendor" == "0x8086" ]] || continue
driver="$(awk -F= '/^DRIVER=/{print $2}' "$d/device/uevent")"
bdf="$(basename "$(readlink -f "$d/device")")"
entries+=("$bdf|$driver")
done
((${#entries[@]})) || return 1
# Sort by BDF (purely cosmetic — selection priorities below don't depend
# on order, and ZE_AFFINITY_MASK takes the BDF directly)
IFS=$'\n' read -rd '' -a entries < <(printf '%s\n' "${entries[@]}" | sort; printf '\0') || true
local picked_bdf="" picked_drv=""
local n=${#entries[@]} i e b drv
# Priority 1: discrete xe device (NOT on PCI bus 00 — those are SoC iGPUs)
for ((i=0; i<n; i++)); do
e="${entries[i]}"; b="${e%%|*}"; drv="${e##*|}"
if [[ "$drv" == "xe" && ! "$b" =~ ^0000:00: ]]; then
picked_bdf="$b"; picked_drv="$drv"; break
fi
done
# Priority 2: any xe device (covers Panther Lake Xe3-LPG iGPU)
if [[ -z "$picked_bdf" ]]; then
for ((i=0; i<n; i++)); do
e="${entries[i]}"; b="${e%%|*}"; drv="${e##*|}"
if [[ "$drv" == "xe" ]]; then
picked_bdf="$b"; picked_drv="$drv"; break
fi
done
fi
# Priority 3: first Intel device (last-resort fallback)
if [[ -z "$picked_bdf" ]]; then
picked_bdf="${entries[0]%%|*}"
picked_drv="${entries[0]##*|}"
fi
echo "$picked_bdf" "$picked_drv"
}
if [[ "${RESOLVE_NO_PIN:-0}" != "1" ]]; then
if [[ -n "${RESOLVE_GPU_BDF:-}" ]]; then
export ZE_AFFINITY_MASK="${RESOLVE_GPU_BDF}"
echo "Resolve: ZE_AFFINITY_MASK=${ZE_AFFINITY_MASK} (manual override via RESOLVE_GPU_BDF)" >&2
ARC_BDF="${RESOLVE_GPU_BDF}"
elif read -r ARC_BDF ARC_DRV < <(arc_pick); then
export ZE_AFFINITY_MASK="${ARC_BDF}"
echo "Resolve: pinning to Arc GPU at ${ARC_BDF} (driver=${ARC_DRV})" >&2
else
echo "Resolve: no Intel GPU found; not pinning ZE_AFFINITY_MASK" >&2
fi
fi
# OpenCL init workaround is specific to discrete Battlemage Xe2 silicon
# (Arc B5x0/B7x0 dGPU). Intel reuses the "Arc B-series" brand for the Xe3-LPG
# iGPUs in Panther Lake (B360/B370/B380/B390, launched Jan 2026), but those
# don't need — and don't want — this debug key. Gate on lspci match AND a
# non-SoC PCI bus, since iGPUs always live on 0000:00:02.0.
if lspci -nn 2>/dev/null | grep -qi 'Battlemage' \
&& [[ -n "${ARC_BDF:-}" && ! "${ARC_BDF}" =~ ^0000:00: ]]; then
export NEOReadDebugKeys=1
export OverrideGpuAddressSpace=48
fi
exec /opt/resolve/bin/resolve "$@"
EOF
sudo chmod +x /usr/local/bin/resolve-intel-arc
# Convenience symlink at /usr/bin/davinci-resolve
if [[ ! -e /usr/bin/davinci-resolve ]]; then
if [[ -x /usr/local/bin/resolve-intel-arc ]]; then
echo -e '#!/usr/bin/env bash\nexec /usr/local/bin/resolve-intel-arc "$@"' | sudo tee /usr/bin/davinci-resolve >/dev/null
else
echo -e '#!/usr/bin/env bash\nexec /opt/resolve/bin/resolve "$@"' | sudo tee /usr/bin/davinci-resolve >/dev/null
fi
sudo chmod +x /usr/bin/davinci-resolve
fi
# Point system .desktop entries at the wrapper
WRAPPER="/usr/local/bin/resolve-intel-arc"
if [[ -f /usr/share/applications/DaVinciResolve.desktop ]]; then
sudo sed -i "s|^Exec=.*|Exec=${WRAPPER} %U|" /usr/share/applications/DaVinciResolve.desktop
fi
if [[ -f /usr/share/applications/DaVinciResolveCaptureLogs.desktop ]]; then
sudo sed -i "s|^Exec=.*|Exec=${WRAPPER} %U|" /usr/share/applications/DaVinciResolveCaptureLogs.desktop
fi
sudo update-desktop-database >/dev/null 2>&1 || true
# User-level .desktop overrides system entry (survives reinstalls)
mkdir -p "${HOME}/.local/share/applications"
cat > "${HOME}/.local/share/applications/davinci-resolve-wrapper.desktop" << EOF
[Desktop Entry]
Type=Application
Name=DaVinci Resolve
Comment=DaVinci Resolve via XWayland wrapper (Intel Arc)
Exec=${WRAPPER} %U
TryExec=${WRAPPER}
Terminal=false
Icon=davinci-resolve
Categories=AudioVideo;Video;Audio;Graphics;
StartupWMClass=resolve
X-GNOME-UsesNotifications=true
EOF
update-desktop-database "${HOME}/.local/share/applications" >/dev/null 2>&1 || true
sudo gtk-update-icon-cache -f /usr/share/icons/hicolor >/dev/null 2>&1 || true
# ==================== Audio backend fix (DeckLink → ALSA) ====================
#
# Resolve ships with `Local.Audio.Type = DeckLink` as the default in its
# system-wide config template at /opt/resolve/share/default-config.dat.
# That's correct for users with a Blackmagic DeckLink capture/playback card,
# but on systems without one Resolve aborts on first launch. Patch both the
# template (so future first-launches are correct) and any existing user
# config (so the current install isn't broken).
log "Switching Resolve audio backend default from DeckLink to ALSA..."
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}"
log " Patched system template ${TEMPLATE}"
fi
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}"
log " Patched existing user config ${USER_CFG} (backup .bak.<timestamp> created)"
fi
# ==================== snd-aloop (the actual render-blocker fix) ====================
#
# Resolve's audio engine opens raw ALSA hardware via snd_pcm_open("hw:%d", ...)
# — it never goes through ALSA's plugin layer (default/pulse/pipewire) and it
# enumerates EVERY card under /dev/snd/controlC[0-32] looking for a usable PCM.
# When every real ALSA card on the system is owned/contested by PipeWire's
# session manager, Resolve's enumeration loops forever, the render queue
# never spawns the encoder, and the user sees:
# - alsa device meters "flickering" in wireplumber (each enumeration cycle
# briefly opens controlC*; PipeWire reacts)
# - render that "won't start" with no error in ResolveDebug.txt
# Confirmed via strace: 14000+ SNDRV_CTL_IOCTL_PCM_INFO ENXIO ioctls and
# 47000+ /dev/snd/controlCN ENOENT opens during the failed render attempt,
# concentrated AFTER the user clicks Render — i.e. a tight retry loop.
#
# THE FIX: load the kernel's snd-aloop module. It exposes a virtual ALSA
# loopback card that PipeWire ignores (no ACP profile, not auto-acquired).
# Resolve's enumerator finds it, can fully own it, settles on it, and the
# render proceeds. Side effect: a "Loopback" device shows up in alsamixer
# and pavucontrol — harmless.
#
# Skipped if RESOLVE_NO_ALOOP=1 (e.g. user already has a dedicated audio
# interface that Resolve uses). Persistent across reboots via
# /etc/modules-load.d/.
if [[ "${RESOLVE_NO_ALOOP:-0}" == "1" ]]; then
log "Skipping snd-aloop setup (RESOLVE_NO_ALOOP=1)"
else
log "Setting up snd-aloop (virtual ALSA card so Resolve render can start)..."
if ! lsmod | grep -qE '^snd_aloop'; then
if sudo modprobe snd-aloop 2>/dev/null; then
log " snd-aloop loaded for the current session"
else
warn " modprobe snd-aloop failed — kernel may lack the module."
warn " On Arch this is part of linux/linux-zen/linux-lts; verify: modinfo snd-aloop"
fi
else
log " snd-aloop already loaded"
fi
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
log " Wrote ${ALOOP_CONF} (autoloads at boot)"
else
log " ${ALOOP_CONF} already configured"
fi
# Bridge snd-aloop capture → default sink so monitor audio is audible.
# Without this, Resolve writes to the loopback and the audio goes nowhere
# (loopback is a black hole until something captures the other side).
# The bridge is a PipeWire loopback module loaded from user config; it
# tracks the default sink so headphone/HDMI switching keeps working.
ALOOP_BRIDGE_DIR="${HOME}/.config/pipewire/pipewire.conf.d"
ALOOP_BRIDGE_FILE="${ALOOP_BRIDGE_DIR}/50-resolve-aloop-bridge.conf"
mkdir -p "${ALOOP_BRIDGE_DIR}"
if [[ ! -f "${ALOOP_BRIDGE_FILE}" ]]; then
cat > "${ALOOP_BRIDGE_FILE}" <<'EOF'
# DaVinci Resolve aloop monitor bridge — managed by install-davinci-resolve-intel-arc.sh
# Bridges snd-aloop's capture side to the system default sink so Resolve's
# monitor audio is audible while editing. Without this, Resolve renders fine
# 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
log " Wrote ${ALOOP_BRIDGE_FILE} (PipeWire loopback bridge)"
# Reload user PipeWire services so the new conf is picked up
if systemctl --user is-active --quiet pipewire 2>/dev/null; then
systemctl --user restart pipewire pipewire-pulse wireplumber 2>/dev/null || true
log " Reloaded user PipeWire services"
fi
else
log " ${ALOOP_BRIDGE_FILE} already in place"
fi
fi
# ==================== Post-install OpenCL sanity check ====================
echo
if command -v clinfo >/dev/null 2>&1; then
if clinfo -l 2>/dev/null | grep -qiE 'Arc|Intel.*Graphics|Battlemage|Alchemist'; then
log "OpenCL: Intel GPU is visible to clinfo — Resolve should see it for compute."
else
warn "OpenCL: no Intel GPU listed by clinfo. Resolve will likely fall back to CPU."
warn " Try: clinfo -l (and check that intel-compute-runtime is installed)"
fi
else
warn "clinfo not installed — skipped OpenCL visibility check"
fi
# ==================== Reset stale Resolve user configs ====================
#
# Resolve defaults to GPU Processing Mode = CUDA on Linux. If a previous
# launch couldn't find an OpenCL device (e.g. Intel compute runtime was
# missing), Resolve writes out a config snapshot and segfaults before the
# UI ever appears 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 with a working GPU
# stack present.
#
# We only wipe if we detect that prior-crash marker (or RESOLVE_RESET_CONFIG=1
# is set explicitly). Project databases under "Resolve Disk Database/" and
# "Resolve Project Library/" are NOT touched.
RESOLVE_USER_DIR="${HOME}/.local/share/DaVinciResolve"
PRIOR_CRASH=0
if [[ -f "${RESOLVE_USER_DIR}/logs/ResolveDebug.txt" ]] \
&& grep -q 'Unsupported GPU Processing Mode' "${RESOLVE_USER_DIR}/logs/ResolveDebug.txt" 2>/dev/null; then
PRIOR_CRASH=1
fi
if (( PRIOR_CRASH )) || [[ "${RESOLVE_RESET_CONFIG:-0}" == "1" ]]; then
if (( PRIOR_CRASH )); then
log "Detected prior crashed launch ('Unsupported GPU Processing Mode')."
else
log "RESOLVE_RESET_CONFIG=1 set — forcing config reset."
fi
log "Resetting Resolve configs and logs to first-launch state. Project databases preserved."
rm -rf "${RESOLVE_USER_DIR}/configs" "${RESOLVE_USER_DIR}/logs" 2>/dev/null || true
fi
echo
echo "✅ DaVinci Resolve installed to /opt/resolve"
echo " (vendor libc++ kept; libcrypt.so.1 ensured; Intel Arc OpenCL/VA-API enabled)"
echo " Launch from your app menu, or run: resolve-intel-arc"
echo " GPU pinning is automatic — discrete Arc preferred over iGPU."
echo " Override: RESOLVE_GPU_BDF=0000:XX:YY.Z resolve-intel-arc"
echo " Disable: RESOLVE_NO_PIN=1 resolve-intel-arc"
echo " Force config reset on next install: RESOLVE_RESET_CONFIG=1 ./install-davinci-resolve-intel-arc.sh"
echo " Skip snd-aloop module setup: RESOLVE_NO_ALOOP=1 ./install-davinci-resolve-intel-arc.sh"
echo " Logs: ~/.local/share/DaVinciResolve/logs/ResolveDebug.txt"
echo " Note: Intel Arc on Linux is unsupported by Blackmagic — expect quirks."
echo