Last active
March 9, 2026 03:28
-
-
Save reoring/e77be94092342b1b968714e276616eb0 to your computer and use it in GitHub Desktop.
Arch Linux DaVinci Resolve Install Script (ROCm 7.1.1 + XWayland)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| # Why this script exists: | |
| # - The AUR package cannot auto-download the Blackmagic ZIP, so we stage it first. | |
| # - Resolve 20.3.x starts but later crashes with opencl-mesa/Rusticl on this AMD system. | |
| # - Resolve 20.3.x also fails very early with ROCm/OpenCL 7.2.x here. | |
| # - ROCm OpenCL 7.1.1 plus XWayland has been the stable combination. | |
| # - The launcher also clears stale Resolve lock/socket files that can block relaunches. | |
| # | |
| # Tested on: Arch + AMD Radeon 8060S + DaVinci Resolve 20.3. | |
| usage() { | |
| cat <<'EOF' | |
| Install DaVinci Resolve on Arch Linux and set up a ROCm/XWayland launcher. | |
| This script expects the official Blackmagic ZIP to be downloaded manually. | |
| It installs the AUR package, downgrades the ROCm OpenCL stack to 7.1.1, | |
| and creates a launcher that uses the known-good Resolve settings. | |
| Usage: | |
| ./install-davinci.sh [options] | |
| Options: | |
| --zip PATH Path to DaVinci_Resolve_*_Linux.zip | |
| --studio Install davinci-resolve-studio instead of davinci-resolve | |
| --scale FACTOR Set default UI scale in the launcher (default: 1.5) | |
| --keep-mesa Do not remove opencl-mesa if installed | |
| --no-desktop Skip creating a desktop launcher override | |
| -y, --yes Non-interactive install where possible | |
| -h, --help Show help | |
| Examples: | |
| ./install-davinci.sh | |
| ./install-davinci.sh --zip ~/Downloads/DaVinci_Resolve_20.3.2_Linux.zip | |
| ./install-davinci.sh --scale 1.5 | |
| EOF | |
| } | |
| need_cmd() { | |
| command -v "$1" >/dev/null 2>&1 || { | |
| printf 'Missing required command: %s\n' "$1" >&2 | |
| exit 1 | |
| } | |
| } | |
| as_root() { | |
| if [[ ${EUID:-0} -eq 0 ]]; then | |
| "$@" | |
| else | |
| need_cmd sudo | |
| sudo "$@" | |
| fi | |
| } | |
| detect_os() { | |
| if [[ -r /etc/os-release ]]; then | |
| # shellcheck disable=SC1091 | |
| . /etc/os-release | |
| printf '%s\n' "${ID:-unknown}" | |
| else | |
| printf 'unknown\n' | |
| fi | |
| } | |
| pick_zip() { | |
| local newest="" | |
| local newest_mtime=0 | |
| local search_dir file mtime | |
| # Prefer the newest matching ZIP from the current directory or Downloads so the | |
| # common manual-download workflow works without extra flags. | |
| shopt -s nullglob | |
| for search_dir in "$PWD" "$HOME/Downloads"; do | |
| [[ -d "$search_dir" ]] || continue | |
| for file in "$search_dir"/DaVinci_Resolve_*_Linux.zip; do | |
| [[ -f "$file" ]] || continue | |
| mtime=$(stat -c '%Y' "$file") | |
| if (( mtime > newest_mtime )); then | |
| newest="$file" | |
| newest_mtime=$mtime | |
| fi | |
| done | |
| done | |
| shopt -u nullglob | |
| [[ -n "$newest" ]] || return 1 | |
| printf '%s\n' "$newest" | |
| } | |
| ZIP_PATH="" | |
| PACKAGE_NAME="davinci-resolve" | |
| SCALE_FACTOR="1.5" | |
| KEEP_MESA=0 | |
| NO_DESKTOP=0 | |
| YES=0 | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| --zip) | |
| ZIP_PATH="${2:-}" | |
| shift 2 | |
| ;; | |
| --studio) | |
| PACKAGE_NAME="davinci-resolve-studio" | |
| shift | |
| ;; | |
| --scale) | |
| SCALE_FACTOR="${2:-}" | |
| shift 2 | |
| ;; | |
| --keep-mesa) | |
| KEEP_MESA=1 | |
| shift | |
| ;; | |
| --no-desktop) | |
| NO_DESKTOP=1 | |
| shift | |
| ;; | |
| -y|--yes) | |
| YES=1 | |
| shift | |
| ;; | |
| -h|--help) | |
| usage | |
| exit 0 | |
| ;; | |
| *) | |
| printf 'Unknown option: %s\n\n' "$1" >&2 | |
| usage >&2 | |
| exit 2 | |
| ;; | |
| esac | |
| done | |
| if [[ -z "$ZIP_PATH" ]]; then | |
| if ! ZIP_PATH="$(pick_zip)"; then | |
| cat >&2 <<'EOF' | |
| Could not find a DaVinci Resolve ZIP automatically. | |
| Download it from https://www.blackmagicdesign.com/support/ | |
| then re-run with: | |
| ./install-davinci.sh --zip ~/Downloads/DaVinci_Resolve_<version>_Linux.zip | |
| EOF | |
| exit 1 | |
| fi | |
| fi | |
| if [[ ! -f "$ZIP_PATH" ]]; then | |
| printf 'ZIP not found: %s\n' "$ZIP_PATH" >&2 | |
| exit 1 | |
| fi | |
| case "$(basename "$ZIP_PATH")" in | |
| DaVinci_Resolve_*_Linux.zip) | |
| ;; | |
| *) | |
| printf 'Unexpected ZIP name: %s\n' "$(basename "$ZIP_PATH")" >&2 | |
| printf 'Expected something like DaVinci_Resolve_20.3.2_Linux.zip\n' >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| if [[ "$(detect_os)" != "arch" ]]; then | |
| printf 'This script supports Arch Linux only.\n' >&2 | |
| exit 2 | |
| fi | |
| if [[ ! "$SCALE_FACTOR" =~ ^[0-9]+([.][0-9]+)?$ ]]; then | |
| printf 'Invalid scale factor: %s\n' "$SCALE_FACTOR" >&2 | |
| exit 2 | |
| fi | |
| need_cmd pacman | |
| need_cmd yay | |
| need_cmd install | |
| need_cmd stat | |
| PACMAN_SYNC_ARGS=(--needed) | |
| PACMAN_URL_ARGS=() | |
| PACMAN_REMOVE_ARGS=(-Rns) | |
| YAY_ARGS=(--needed) | |
| if [[ $YES -eq 1 ]]; then | |
| PACMAN_SYNC_ARGS+=(--noconfirm) | |
| PACMAN_URL_ARGS+=(--noconfirm) | |
| PACMAN_REMOVE_ARGS+=(--noconfirm) | |
| YAY_ARGS+=(--noconfirm) | |
| fi | |
| CACHE_DIR="$HOME/.cache/yay/$PACKAGE_NAME" | |
| WRAPPER_DIR="$HOME/.local/bin" | |
| APP_DIR="$HOME/.local/share/applications" | |
| WRAPPER_PATH="$WRAPPER_DIR/davinci-resolve-rocm" | |
| LEGACY_WRAPPER_PATH="$WRAPPER_DIR/davinci-resolve-mesa" | |
| DESKTOP_PATH="$APP_DIR/DaVinciResolve.desktop" | |
| ROCM_OPENCL_LIB="/opt/rocm/lib/libamdocl64.so" | |
| # Pinned ROCm package set: 7.1.1 is the known-good version for this machine. | |
| # Newer 7.2.x packages caused Resolve to crash during GPU detection. | |
| ROCM_PACKAGES=( | |
| "https://archive.archlinux.org/packages/h/hsa-rocr/hsa-rocr-7.1.1-2-x86_64.pkg.tar.zst" | |
| "https://archive.archlinux.org/packages/s/spirv-llvm-translator/spirv-llvm-translator-21.1.3-1-x86_64.pkg.tar.zst" | |
| "https://archive.archlinux.org/packages/r/rocminfo/rocminfo-7.1.1-1-x86_64.pkg.tar.zst" | |
| "https://archive.archlinux.org/packages/r/rocm-core/rocm-core-7.1.1-1-x86_64.pkg.tar.zst" | |
| "https://archive.archlinux.org/packages/r/rocm-device-libs/rocm-device-libs-2%3A7.1.1-2-x86_64.pkg.tar.zst" | |
| "https://archive.archlinux.org/packages/r/rocm-opencl-runtime/rocm-opencl-runtime-7.1.1-1-x86_64.pkg.tar.zst" | |
| "https://archive.archlinux.org/packages/r/rocm-llvm/rocm-llvm-2%3A7.1.1-2-x86_64.pkg.tar.zst" | |
| ) | |
| printf '==> Using ZIP: %s\n' "$ZIP_PATH" | |
| printf '==> Installing package prerequisites\n' | |
| as_root pacman -S "${PACMAN_SYNC_ARGS[@]}" clinfo | |
| printf '==> Staging installer ZIP for %s\n' "$PACKAGE_NAME" | |
| mkdir -p "$CACHE_DIR" | |
| install -m 644 "$ZIP_PATH" "$CACHE_DIR/$(basename "$ZIP_PATH")" | |
| printf '==> Installing %s\n' "$PACKAGE_NAME" | |
| yay -S "${YAY_ARGS[@]}" "$PACKAGE_NAME" | |
| # Install the full matching ROCm userspace set together. Mixing only some 7.1.1 | |
| # packages with newer system packages is more likely to break OpenCL loading. | |
| printf '==> Installing ROCm OpenCL 7.1.1 packages\n' | |
| as_root pacman -U "${PACMAN_URL_ARGS[@]}" "${ROCM_PACKAGES[@]}" | |
| if [[ $KEEP_MESA -eq 0 ]] && pacman -Q opencl-mesa >/dev/null 2>&1; then | |
| # Rusticl is good enough for startup on this system but later crashes once | |
| # Resolve reaches real project/media work, so remove it by default. | |
| printf '==> Removing opencl-mesa to avoid Rusticl crashes in Resolve\n' | |
| as_root pacman "${PACMAN_REMOVE_ARGS[@]}" opencl-mesa || true | |
| fi | |
| printf '==> Creating launcher wrapper at %s\n' "$WRAPPER_PATH" | |
| mkdir -p "$WRAPPER_DIR" | |
| cat >"$WRAPPER_PATH" <<EOF | |
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| DEFAULT_UI_SCALE="$SCALE_FACTOR" | |
| ROCM_OPENCL_LIB="$ROCM_OPENCL_LIB" | |
| # Resolve leaves stale singleton lock files and a socket behind after some | |
| # crashes. Clearing them before launch avoids the "Accepted new client" loop. | |
| if ! pgrep -f '/opt/resolve/bin/resolve' >/dev/null 2>&1; then | |
| rm -f /tmp/qtsingleapp-DaVinc-* /tmp/qtsingleapp-DaVinc-*-lockfile | |
| rm -f /var/tmp/davinci_socket | |
| fi | |
| if [[ ! -r "\$ROCM_OPENCL_LIB" ]]; then | |
| printf 'Missing ROCm OpenCL library: %s\n' "\$ROCM_OPENCL_LIB" >&2 | |
| exit 1 | |
| fi | |
| # Resolve behaves best here when we force XWayland (`xcb`), ignore desktop Qt | |
| # theme overrides like Kvantum, and explicitly point OpenCL to the ROCm ICD. | |
| ENV_ARGS=( | |
| -u QT_QPA_PLATFORM | |
| -u QT_PLUGIN_PATH | |
| -u QML2_IMPORT_PATH | |
| -u QT_QPA_PLATFORMTHEME | |
| -u QT_STYLE_OVERRIDE | |
| -u QT_SCALE_FACTOR | |
| -u QT_SCREEN_SCALE_FACTORS | |
| -u OCL_ICD_VENDORS | |
| -u OCL_ICD_FILENAMES | |
| -u RUSTICL_ENABLE | |
| QT_QPA_PLATFORM=xcb | |
| QT_AUTO_SCREEN_SCALE_FACTOR=1 | |
| OCL_ICD_VENDORS= | |
| OCL_ICD_FILENAMES="\$ROCM_OPENCL_LIB" | |
| ) | |
| UI_SCALE="\${DAVINCI_UI_SCALE:-\$DEFAULT_UI_SCALE}" | |
| if [[ -n "\$UI_SCALE" ]]; then | |
| ENV_ARGS+=(QT_SCALE_FACTOR="\$UI_SCALE") | |
| fi | |
| exec env "\${ENV_ARGS[@]}" /usr/bin/davinci-resolve "\$@" | |
| EOF | |
| chmod +x "$WRAPPER_PATH" | |
| # Keep the old wrapper name as a thin alias so any existing shell history, | |
| # launchers, or scripts continue to work after the ROCm migration. | |
| cat >"$LEGACY_WRAPPER_PATH" <<EOF | |
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| exec "$WRAPPER_PATH" "\$@" | |
| EOF | |
| chmod +x "$LEGACY_WRAPPER_PATH" | |
| if [[ $NO_DESKTOP -eq 0 ]]; then | |
| printf '==> Creating desktop launcher override at %s\n' "$DESKTOP_PATH" | |
| mkdir -p "$APP_DIR" | |
| cat >"$DESKTOP_PATH" <<EOF | |
| [Desktop Entry] | |
| Version=1.0 | |
| Type=Application | |
| Name=DaVinci Resolve | |
| GenericName=DaVinci Resolve | |
| Comment=Launch DaVinci Resolve with ROCm OpenCL and XWayland | |
| Path=/opt/resolve/ | |
| Exec=$WRAPPER_PATH %u | |
| Terminal=false | |
| MimeType=application/x-resolveproj; | |
| Icon=davinci-resolve | |
| StartupNotify=true | |
| StartupWMClass=resolve | |
| EOF | |
| fi | |
| printf '==> Done\n' | |
| printf 'Launch from terminal with: %s\n' "$WRAPPER_PATH" | |
| printf 'Legacy compatibility wrapper: %s\n' "$LEGACY_WRAPPER_PATH" | |
| printf 'Default UI scale in launcher: %s\n' "$SCALE_FACTOR" | |
| printf 'ROCm OpenCL path: %s\n' "$ROCM_OPENCL_LIB" | |
| if [[ $NO_DESKTOP -eq 0 ]]; then | |
| printf 'The desktop launcher now points to the ROCm wrapper too.\n' | |
| fi |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Tested on: Arch + AMD Radeon 8060S + DaVinci Resolve 20.3.2