1870 lines
61 KiB
Bash
Executable file
1870 lines
61 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# =============================================================================
|
|
# DaVinci Resolve Free - Arch Linux + AMD RX 9000 + Hyprland Install Script
|
|
# =============================================================================
|
|
#
|
|
# Version 3.0 - Davincibox-style fixes for better compatibility
|
|
# Validated against Arch Wiki, AUR, davincibox, and community docs (Dec 2025)
|
|
#
|
|
# 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)
|
|
#
|
|
# Based on techniques from:
|
|
# - https://github.com/zelikos/davincibox
|
|
# - https://wiki.archlinux.org/title/DaVinci_Resolve
|
|
#
|
|
# Usage:
|
|
# chmod +x install-davinci-resolve.sh
|
|
# ./install-davinci-resolve.sh
|
|
#
|
|
# =============================================================================
|
|
|
|
set -e
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
MAGENTA='\033[0;35m'
|
|
BOLD='\033[1m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Logging functions
|
|
info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
success() { echo -e "${GREEN}[OK]${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
|
|
header() { echo -e "\n${CYAN}=== $1 ===${NC}\n"; }
|
|
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"
|
|
|
|
# =============================================================================
|
|
# SYSTEM SCAN VARIABLES (populated during scan)
|
|
# =============================================================================
|
|
|
|
# System info
|
|
SCAN_KERNEL_VERSION=""
|
|
SCAN_KERNEL_MAJOR=0
|
|
SCAN_KERNEL_MINOR=0
|
|
SCAN_ARCH=""
|
|
|
|
# GPU info - Single GPU (legacy/primary)
|
|
SCAN_GPU_VENDOR=""
|
|
SCAN_GPU_MODEL=""
|
|
SCAN_GPU_DRIVER=""
|
|
SCAN_GPU_RDNA_VERSION=""
|
|
SCAN_IS_RDNA4=false
|
|
|
|
# GPU info - Multi-GPU support
|
|
SCAN_GPU_COUNT=0
|
|
SCAN_GPUS=()
|
|
SCAN_GPU_VENDORS=()
|
|
SCAN_GPU_MODELS=()
|
|
SCAN_GPU_TYPES=()
|
|
SCAN_GPU_PCI_IDS=()
|
|
SCAN_GPU_RDNA_VERSIONS=()
|
|
SCAN_GPU_DRIVERS_LOADED=()
|
|
SCAN_PRIMARY_GPU_INDEX=0
|
|
|
|
# Hybrid GPU flags
|
|
SCAN_HAS_IGPU=false
|
|
SCAN_HAS_DGPU=false
|
|
SCAN_HAS_AMD_DGPU=false
|
|
SCAN_HAS_NVIDIA_DGPU=false
|
|
SCAN_HAS_AMD_IGPU=false
|
|
SCAN_HAS_INTEL_IGPU=false
|
|
SCAN_IS_HYBRID=false
|
|
SCAN_PRIME_AVAILABLE=false
|
|
|
|
# Mesa/Graphics
|
|
SCAN_MESA_VERSION=""
|
|
SCAN_MESA_MAJOR=0
|
|
SCAN_VULKAN_AVAILABLE=false
|
|
SCAN_OPENGL_RENDERER=""
|
|
|
|
# OpenCL
|
|
SCAN_OPENCL_INSTALLED=false
|
|
SCAN_OPENCL_PROVIDER=""
|
|
SCAN_OPENCL_PLATFORMS=""
|
|
SCAN_AMD_OPENCL_WORKING=false
|
|
|
|
# Audio
|
|
SCAN_AUDIO_SERVER=""
|
|
SCAN_PIPEWIRE_INSTALLED=false
|
|
SCAN_PULSEAUDIO_INSTALLED=false
|
|
|
|
# Display
|
|
SCAN_DISPLAY_SERVER=""
|
|
SCAN_COMPOSITOR=""
|
|
SCAN_HYPRLAND_INSTALLED=false
|
|
SCAN_HYPRLAND_RUNNING=false
|
|
|
|
# DaVinci Resolve
|
|
SCAN_RESOLVE_INSTALLED=false
|
|
SCAN_RESOLVE_VERSION=""
|
|
SCAN_RESOLVE_PATH=""
|
|
|
|
# Package manager
|
|
SCAN_AUR_HELPER=""
|
|
|
|
# Disk space
|
|
SCAN_ROOT_FREE_GB=0
|
|
SCAN_HOME_FREE_GB=0
|
|
|
|
# Existing packages (to avoid reinstalling)
|
|
SCAN_INSTALLED_PACKAGES=""
|
|
|
|
# =============================================================================
|
|
# SYSTEM SCAN FUNCTIONS
|
|
# =============================================================================
|
|
|
|
scan_kernel() {
|
|
SCAN_KERNEL_VERSION=$(uname -r)
|
|
SCAN_KERNEL_MAJOR=$(echo "$SCAN_KERNEL_VERSION" | cut -d'.' -f1)
|
|
SCAN_KERNEL_MINOR=$(echo "$SCAN_KERNEL_VERSION" | cut -d'.' -f2)
|
|
SCAN_ARCH=$(uname -m)
|
|
}
|
|
|
|
scan_gpu() {
|
|
# Arrays for multi-GPU detection
|
|
SCAN_GPU_COUNT=0
|
|
SCAN_GPUS=() # Array of GPU info strings
|
|
SCAN_GPU_VENDORS=() # Array of vendors
|
|
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
|
|
SCAN_HAS_AMD_DGPU=false
|
|
SCAN_HAS_NVIDIA_DGPU=false
|
|
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
|
|
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"
|
|
SCAN_HAS_IGPU=true
|
|
SCAN_HAS_AMD_IGPU=true
|
|
else
|
|
gpu_type="discrete"
|
|
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"
|
|
SCAN_IS_RDNA4=true
|
|
elif echo "$gpu_line" | grep -qiE "7[0-9]{3}|Navi 3|gfx11"; then
|
|
rdna_ver="RDNA3"
|
|
elif echo "$gpu_line" | grep -qiE "6[0-9]{3}|Navi 2|gfx103"; then
|
|
rdna_ver="RDNA2"
|
|
elif echo "$gpu_line" | grep -qiE "5[0-9]{3}|Navi 1|gfx101"; then
|
|
rdna_ver="RDNA1"
|
|
elif echo "$gpu_line" | grep -qiE "Vega|gfx9"; then
|
|
rdna_ver="Vega"
|
|
elif echo "$gpu_line" | grep -qiE "Phoenix|Hawk Point|Strix"; then
|
|
rdna_ver="RDNA3 (iGPU)"
|
|
elif echo "$gpu_line" | grep -qiE "Rembrandt|Barcelo"; then
|
|
rdna_ver="RDNA2 (iGPU)"
|
|
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"
|
|
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
|
|
if [[ "$vendor" == "AMD" ]]; then
|
|
SCAN_GPU_RDNA_VERSIONS+=("$rdna_ver")
|
|
else
|
|
SCAN_GPU_RDNA_VERSIONS+=("")
|
|
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
|
|
SCAN_PRIMARY_GPU_INDEX=$i
|
|
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
|
|
if [[ "${SCAN_GPU_VENDORS[$i]}" == "NVIDIA" && "${SCAN_GPU_TYPES[$i]}" == "discrete" ]]; then
|
|
SCAN_PRIMARY_GPU_INDEX=$i
|
|
break
|
|
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]}"
|
|
fi
|
|
|
|
# Check loaded kernel drivers
|
|
SCAN_GPU_DRIVERS_LOADED=()
|
|
if lsmod 2>/dev/null | grep -q "^amdgpu"; then
|
|
SCAN_GPU_DRIVERS_LOADED+=("amdgpu")
|
|
SCAN_GPU_DRIVER="amdgpu"
|
|
fi
|
|
if lsmod 2>/dev/null | grep -q "^nvidia"; then
|
|
SCAN_GPU_DRIVERS_LOADED+=("nvidia")
|
|
[[ -z "$SCAN_GPU_DRIVER" ]] && SCAN_GPU_DRIVER="nvidia"
|
|
fi
|
|
if lsmod 2>/dev/null | grep -q "^i915"; then
|
|
SCAN_GPU_DRIVERS_LOADED+=("i915")
|
|
[[ -z "$SCAN_GPU_DRIVER" ]] && SCAN_GPU_DRIVER="i915"
|
|
fi
|
|
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
|
|
# Check if DRI_PRIME would work
|
|
if [[ -d "/sys/class/drm" ]]; then
|
|
local render_nodes=$(ls /dev/dri/renderD* 2>/dev/null | wc -l)
|
|
if [[ $render_nodes -gt 1 ]]; then
|
|
SCAN_PRIME_AVAILABLE=true
|
|
fi
|
|
fi
|
|
fi
|
|
}
|
|
|
|
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
|
|
fi
|
|
}
|
|
|
|
scan_opencl() {
|
|
# Check what OpenCL packages are installed
|
|
# Check for full ROCm stack first (preferred for RDNA4)
|
|
if pacman -Qq rocm-opencl-runtime &>/dev/null; then
|
|
SCAN_OPENCL_INSTALLED=true
|
|
# Check if full ROCm stack is installed
|
|
if pacman -Qq rocm-hip-runtime rocm-core &>/dev/null; then
|
|
SCAN_OPENCL_PROVIDER="rocm-full"
|
|
# Get ROCm version
|
|
local rocm_ver=$(pacman -Q rocm-core 2>/dev/null | awk '{print $2}' | cut -d'-' -f1)
|
|
[[ -n "$rocm_ver" ]] && SCAN_OPENCL_PROVIDER="rocm-full ($rocm_ver)"
|
|
else
|
|
SCAN_OPENCL_PROVIDER="rocm-opencl-runtime"
|
|
fi
|
|
elif pacman -Qq opencl-amd &>/dev/null; then
|
|
SCAN_OPENCL_INSTALLED=true
|
|
SCAN_OPENCL_PROVIDER="opencl-amd"
|
|
elif pacman -Qq mesa-opencl &>/dev/null || pacman -Qq opencl-mesa &>/dev/null; then
|
|
SCAN_OPENCL_INSTALLED=true
|
|
SCAN_OPENCL_PROVIDER="mesa (rusticl)"
|
|
elif pacman -Qq intel-compute-runtime &>/dev/null; then
|
|
SCAN_OPENCL_INSTALLED=true
|
|
SCAN_OPENCL_PROVIDER="intel-compute-runtime"
|
|
fi
|
|
|
|
# Check if OpenCL actually works with AMD
|
|
if command -v clinfo &>/dev/null; then
|
|
SCAN_OPENCL_PLATFORMS=$(clinfo --list 2>/dev/null | head -5 || echo "")
|
|
if clinfo --list 2>/dev/null | grep -qi "AMD\|gfx\|Radeon"; then
|
|
SCAN_AMD_OPENCL_WORKING=true
|
|
fi
|
|
fi
|
|
}
|
|
|
|
scan_audio() {
|
|
# Detect audio server
|
|
if command -v pactl &>/dev/null; then
|
|
local server_name=$(pactl info 2>/dev/null | grep "Server Name" || echo "")
|
|
if echo "$server_name" | grep -qi "PipeWire"; then
|
|
SCAN_AUDIO_SERVER="PipeWire"
|
|
SCAN_PIPEWIRE_INSTALLED=true
|
|
elif echo "$server_name" | grep -qi "PulseAudio"; then
|
|
SCAN_AUDIO_SERVER="PulseAudio"
|
|
SCAN_PULSEAUDIO_INSTALLED=true
|
|
fi
|
|
fi
|
|
|
|
# Double-check with package detection
|
|
if pacman -Qq pipewire &>/dev/null; then
|
|
SCAN_PIPEWIRE_INSTALLED=true
|
|
fi
|
|
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
|
|
SCAN_AUDIO_SERVER="PipeWire (detected from packages)"
|
|
elif [[ "$SCAN_PULSEAUDIO_INSTALLED" == true ]]; then
|
|
SCAN_AUDIO_SERVER="PulseAudio (detected from packages)"
|
|
else
|
|
SCAN_AUDIO_SERVER="Unknown/None"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
scan_display() {
|
|
# Detect display server
|
|
if [[ -n "$WAYLAND_DISPLAY" ]]; then
|
|
SCAN_DISPLAY_SERVER="Wayland"
|
|
elif [[ "$XDG_SESSION_TYPE" == "wayland" ]]; then
|
|
# Wayland session but WAYLAND_DISPLAY not set (XWayland context)
|
|
SCAN_DISPLAY_SERVER="Wayland (XWayland available)"
|
|
elif [[ -n "$DISPLAY" ]]; then
|
|
SCAN_DISPLAY_SERVER="X11"
|
|
else
|
|
SCAN_DISPLAY_SERVER="None/TTY"
|
|
fi
|
|
|
|
# Detect compositor
|
|
if [[ -n "$HYPRLAND_INSTANCE_SIGNATURE" ]]; then
|
|
SCAN_COMPOSITOR="Hyprland"
|
|
SCAN_HYPRLAND_RUNNING=true
|
|
elif [[ -n "$SWAYSOCK" ]]; then
|
|
SCAN_COMPOSITOR="Sway"
|
|
elif [[ -n "$GNOME_DESKTOP_SESSION_ID" ]]; then
|
|
SCAN_COMPOSITOR="GNOME"
|
|
elif [[ -n "$KDE_FULL_SESSION" ]]; then
|
|
SCAN_COMPOSITOR="KDE Plasma"
|
|
elif pgrep -x "hyprland" &>/dev/null; then
|
|
SCAN_COMPOSITOR="Hyprland"
|
|
SCAN_HYPRLAND_RUNNING=true
|
|
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
|
|
fi
|
|
}
|
|
|
|
scan_resolve() {
|
|
# Check if DaVinci Resolve is installed
|
|
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
|
|
fi
|
|
}
|
|
|
|
scan_aur_helper() {
|
|
if command -v paru &>/dev/null; then
|
|
SCAN_AUR_HELPER="paru"
|
|
elif command -v yay &>/dev/null; then
|
|
SCAN_AUR_HELPER="yay"
|
|
elif command -v trizen &>/dev/null; then
|
|
SCAN_AUR_HELPER="trizen"
|
|
elif command -v pikaur &>/dev/null; then
|
|
SCAN_AUR_HELPER="pikaur"
|
|
else
|
|
SCAN_AUR_HELPER=""
|
|
fi
|
|
}
|
|
|
|
scan_disk_space() {
|
|
# Get free space in GB
|
|
SCAN_ROOT_FREE_GB=$(df -BG / 2>/dev/null | awk 'NR==2 {print $4}' | tr -d 'G' || echo "0")
|
|
SCAN_HOME_FREE_GB=$(df -BG "$HOME" 2>/dev/null | awk 'NR==2 {print $4}' | tr -d 'G' || echo "0")
|
|
}
|
|
|
|
scan_installed_packages() {
|
|
# Get list of installed packages for comparison
|
|
SCAN_INSTALLED_PACKAGES=$(pacman -Qq 2>/dev/null || echo "")
|
|
}
|
|
|
|
is_pkg_installed() {
|
|
echo "$SCAN_INSTALLED_PACKAGES" | grep -qx "$1"
|
|
}
|
|
|
|
# =============================================================================
|
|
# MAIN SYSTEM SCAN
|
|
# =============================================================================
|
|
|
|
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 ""
|
|
}
|
|
|
|
# =============================================================================
|
|
# DISPLAY SCAN RESULTS
|
|
# =============================================================================
|
|
|
|
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
|
|
for i in "${!SCAN_GPUS[@]}"; do
|
|
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
|
|
|
|
echo -e " PCI: ${SCAN_GPU_PCI_IDS[$i]}"
|
|
done
|
|
|
|
echo ""
|
|
if [[ "$SCAN_IS_HYBRID" == true ]]; then
|
|
echo -e " ${YELLOW}⚡ Hybrid Graphics Detected${NC}"
|
|
if [[ "$SCAN_PRIME_AVAILABLE" == true ]]; then
|
|
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
|
|
scan_item "Provider" "$SCAN_OPENCL_PROVIDER"
|
|
scan_item "AMD Working" "$( [[ "$SCAN_AMD_OPENCL_WORKING" == true ]] && echo "Yes ✓" || echo "No ✗" )"
|
|
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
|
|
scan_item "Status" "Installed"
|
|
scan_item "Version" "${SCAN_RESOLVE_VERSION:-Unknown}"
|
|
scan_item "Path" "$SCAN_RESOLVE_PATH"
|
|
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 ""
|
|
}
|
|
|
|
# =============================================================================
|
|
# ANALYZE SCAN AND PROVIDE RECOMMENDATIONS
|
|
# =============================================================================
|
|
|
|
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++))
|
|
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++))
|
|
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++))
|
|
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 " The launcher script will be configured for this."
|
|
((warnings++))
|
|
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++))
|
|
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++))
|
|
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++))
|
|
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++))
|
|
elif [[ "$SCAN_GPU_VENDOR" == "Intel" ]]; then
|
|
echo -e "${YELLOW}[WARNING]${NC} Only Intel GPU detected. DaVinci Resolve has limited Intel support."
|
|
((warnings++))
|
|
else
|
|
echo -e "${YELLOW}[WARNING]${NC} GPU vendor not recognized. This script is optimized for AMD GPUs."
|
|
((warnings++))
|
|
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++))
|
|
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++))
|
|
fi
|
|
|
|
# RDNA4 info
|
|
if [[ "$SCAN_IS_RDNA4" == true ]]; then
|
|
echo -e "${CYAN}[RDNA4]${NC} Detected RDNA4 GPU (gfx1201)"
|
|
echo " Note: RDNA4 support is new - compatibility may vary"
|
|
echo " If Resolve fails, try switching OPENCL_PROVIDER in script"
|
|
fi
|
|
|
|
# Show selected OpenCL provider with explanation
|
|
echo -e "${CYAN}[CONFIG]${NC} OpenCL provider: $OPENCL_PROVIDER"
|
|
if [[ "$OPENCL_PROVIDER" == "opencl-amd" ]]; then
|
|
echo " Using AUR package (recommended by Arch Wiki for Resolve)"
|
|
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++))
|
|
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++))
|
|
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++))
|
|
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++))
|
|
fi
|
|
|
|
# Summary
|
|
echo ""
|
|
if [[ $issues -eq 0 && $warnings -eq 0 ]]; then
|
|
echo -e "${GREEN}✓ No issues detected. System looks ready for installation.${NC}"
|
|
elif [[ $issues -eq 0 ]]; then
|
|
echo -e "${YELLOW}⚠ $warnings warning(s) detected, but installation can proceed.${NC}"
|
|
else
|
|
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
|
|
}
|
|
|
|
# =============================================================================
|
|
# SMART PACKAGE SELECTION
|
|
# =============================================================================
|
|
|
|
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"
|
|
)
|
|
|
|
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
|
|
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
|
|
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
|
|
fi
|
|
|
|
# Diagnostic tools
|
|
local diag_tools=(
|
|
"clinfo"
|
|
"mesa-utils"
|
|
"expac"
|
|
"python-distro"
|
|
"unzip"
|
|
)
|
|
|
|
for pkg in "${diag_tools[@]}"; 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
|
|
echo " ${PACMAN_PACKAGES[*]}"
|
|
else
|
|
echo " (none needed)"
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${BOLD}Packages to install from AUR:${NC}"
|
|
if [[ ${#AUR_PACKAGES[@]} -gt 0 ]]; then
|
|
echo " ${AUR_PACKAGES[*]}"
|
|
else
|
|
echo " (none needed)"
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${BOLD}Packages already installed (skipping):${NC}"
|
|
if [[ ${#SKIP_PACKAGES[@]} -gt 0 ]]; then
|
|
echo " ${SKIP_PACKAGES[*]}"
|
|
else
|
|
echo " (none)"
|
|
fi
|
|
|
|
echo ""
|
|
}
|
|
|
|
# =============================================================================
|
|
# INSTALLATION FUNCTIONS
|
|
# =============================================================================
|
|
|
|
install_pacman_packages() {
|
|
if [[ ${#PACMAN_PACKAGES[@]} -eq 0 ]]; then
|
|
info "No official repo packages to install."
|
|
return 0
|
|
fi
|
|
|
|
header "Installing Official Repo Packages"
|
|
|
|
# Handle opencl-amd removal when using full ROCm stack
|
|
if [[ "$OPENCL_PROVIDER" == "rocm-full" ]] && is_pkg_installed "opencl-amd"; then
|
|
warn "Removing opencl-amd (AUR) to install official ROCm stack..."
|
|
sudo pacman -Rns opencl-amd --noconfirm 2>/dev/null || true
|
|
fi
|
|
|
|
# Handle OpenCL conflicts - rusticl/mesa-opencl breaks ROCm (confirmed by davincibox)
|
|
# Reference: https://github.com/zelikos/davincibox - "mesa-libOpenCL breaks rocm-opencl"
|
|
local -a opencl_conflicts=()
|
|
for pkg in opencl-rusticl-mesa opencl-clover-mesa mesa-opencl pocl; do
|
|
if is_pkg_installed "$pkg"; then
|
|
opencl_conflicts+=("$pkg")
|
|
fi
|
|
done
|
|
if [[ ${#opencl_conflicts[@]} -gt 0 ]]; then
|
|
warn "Removing conflicting OpenCL packages (breaks ROCm): ${opencl_conflicts[*]}"
|
|
sudo pacman -Rns "${opencl_conflicts[@]}" --noconfirm 2>/dev/null || true
|
|
fi
|
|
|
|
info "Installing ${#PACMAN_PACKAGES[@]} packages..."
|
|
sudo pacman -S --needed --noconfirm "${PACMAN_PACKAGES[@]}"
|
|
|
|
success "Official packages installed."
|
|
}
|
|
|
|
install_aur_packages() {
|
|
if [[ ${#AUR_PACKAGES[@]} -eq 0 ]]; then
|
|
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
|
|
local -a conflicts=()
|
|
for pkg in mesa-opencl pocl intel-compute-runtime rocm-opencl-runtime; do
|
|
if is_pkg_installed "$pkg"; then
|
|
conflicts+=("$pkg")
|
|
fi
|
|
done
|
|
|
|
if [[ ${#conflicts[@]} -gt 0 ]]; then
|
|
warn "Found conflicting OpenCL packages: ${conflicts[*]}"
|
|
read -p "Remove them to install opencl-amd? [Y/n] " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
|
|
sudo pacman -Rns "${conflicts[@]}" --noconfirm 2>/dev/null || true
|
|
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
|
|
|
|
success "AUR packages installed."
|
|
}
|
|
|
|
install_davinci_resolve() {
|
|
if [[ "$SCAN_RESOLVE_INSTALLED" == true ]]; then
|
|
info "DaVinci Resolve already installed. Skipping installation."
|
|
info "Will apply workarounds and configuration updates."
|
|
return 0
|
|
fi
|
|
|
|
header "Installing DaVinci Resolve"
|
|
|
|
# Find installer (handle filenames with spaces properly)
|
|
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)
|
|
|
|
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 ""
|
|
read -p "Open download page? [Y/n] " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
|
|
xdg-open "https://www.blackmagicdesign.com/products/davinciresolve" 2>/dev/null || true
|
|
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)
|
|
if [[ "$major" -lt 20 ]]; then
|
|
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)
|
|
local original_dir="$PWD"
|
|
info "Building in $build_dir..."
|
|
|
|
# Cleanup function for build directory
|
|
cleanup_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
|
|
fi
|
|
fi
|
|
|
|
info "Building package (this takes several minutes)..."
|
|
if [[ "$version_updated" == true ]]; then
|
|
makepkg -si --noconfirm --skipchecksums
|
|
else
|
|
makepkg -si --noconfirm
|
|
fi
|
|
|
|
# Cleanup
|
|
cleanup_build
|
|
trap - EXIT
|
|
|
|
success "DaVinci Resolve installed."
|
|
}
|
|
|
|
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"
|
|
)
|
|
|
|
# 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
|
|
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++))
|
|
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
|
|
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
|
|
fi
|
|
|
|
info "Moving bundled glib libraries (fallback method)..."
|
|
sudo mkdir -p "$resolve_libs/disabled-libraries"
|
|
|
|
# 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)
|
|
|
|
success "Glib fix (fallback) applied."
|
|
}
|
|
|
|
disable_opencl_decoders() {
|
|
# Davincibox-style fix: disable BlackmagicRaw OpenCL decoders to prevent conflicts
|
|
# These are the exact paths from davincibox setup-davinci script
|
|
header "Disabling Problematic OpenCL Decoders"
|
|
|
|
local decoder_paths=(
|
|
# Exact paths from davincibox
|
|
"/opt/resolve/BlackmagicRAWPlayer/BlackmagicRawAPI/libDecoderOpenCL.so"
|
|
"/opt/resolve/BlackmagicRAWSpeedTest/BlackmagicRawAPI/libDecoderOpenCL.so"
|
|
# Additional possible locations
|
|
"/opt/resolve/libs/BlackmagicRawAPI/libDecoderOpenCL.so"
|
|
"/opt/resolve/BlackmagicRawAPI/libDecoderOpenCL.so"
|
|
)
|
|
|
|
local disabled=0
|
|
for decoder in "${decoder_paths[@]}"; do
|
|
if [[ -f "$decoder" && ! -f "${decoder}.bak" ]]; then
|
|
info "Disabling: $decoder"
|
|
sudo mv "$decoder" "${decoder}.bak"
|
|
disabled=$((disabled + 1))
|
|
elif [[ -f "${decoder}.bak" ]]; then
|
|
info "Already disabled: $decoder"
|
|
fi
|
|
done
|
|
|
|
if [[ $disabled -gt 0 ]]; then
|
|
success "Disabled $disabled OpenCL decoder(s) to prevent conflicts."
|
|
else
|
|
info "No OpenCL decoders needed disabling."
|
|
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
|
|
header "Configuring User Groups"
|
|
|
|
local groups_to_add=()
|
|
local current_groups=$(groups "$USER" 2>/dev/null)
|
|
|
|
# Check render group
|
|
if ! echo "$current_groups" | grep -qw "render"; then
|
|
if getent group render &>/dev/null; then
|
|
groups_to_add+=("render")
|
|
else
|
|
info "Group 'render' does not exist on this system (may not be needed)"
|
|
fi
|
|
else
|
|
info "User already in 'render' group"
|
|
fi
|
|
|
|
# Check video group
|
|
if ! echo "$current_groups" | grep -qw "video"; then
|
|
if getent group video &>/dev/null; then
|
|
groups_to_add+=("video")
|
|
fi
|
|
else
|
|
info "User already in 'video' group"
|
|
fi
|
|
|
|
# Add user to missing groups
|
|
if [[ ${#groups_to_add[@]} -gt 0 ]]; then
|
|
info "Adding user to groups: ${groups_to_add[*]}"
|
|
for grp in "${groups_to_add[@]}"; do
|
|
sudo usermod -a -G "$grp" "$USER"
|
|
done
|
|
warn "You will need to log out and back in for group changes to take effect!"
|
|
success "User added to required groups."
|
|
else
|
|
success "User already has required group memberships."
|
|
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"
|
|
|
|
local udev_rule_file="/etc/udev/rules.d/75-davinci-resolve-dongle.rules"
|
|
local udev_rule='SUBSYSTEM=="usb", ATTR{idVendor}=="096e", MODE="0666"'
|
|
|
|
# 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"
|
|
|
|
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
|
|
else
|
|
info "DaVinci Resolve Free detected - USB dongle rule not needed."
|
|
fi
|
|
else
|
|
info "DaVinci Resolve not yet installed - skipping USB dongle setup."
|
|
fi
|
|
}
|
|
|
|
create_launcher() {
|
|
header "Creating 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
|
|
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
|
|
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='
|
|
# 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
|
|
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"
|
|
|
|
# Enable RDNA4 support (gfx1201)
|
|
export HSA_OVERRIDE_GFX_VERSION=11.0.1
|
|
|
|
# ROCm OpenCL configuration
|
|
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
|
|
#!/bin/bash
|
|
# DaVinci Resolve Launcher with workarounds
|
|
# Generated by install script on $(date)
|
|
# OpenCL Provider: $OPENCL_PROVIDER
|
|
# Fixes applied: patchelf (davincibox method)
|
|
|
|
# Qt configuration for XWayland
|
|
export QT_QPA_PLATFORM=xcb
|
|
export QT_AUTO_SCREEN_SCALE_FACTOR=1
|
|
${prime_config}
|
|
${rocm_config}
|
|
|
|
# Increase file descriptor limit for large projects
|
|
ulimit -n 65535 2>/dev/null
|
|
|
|
exec /opt/resolve/bin/resolve "\$@"
|
|
EOF
|
|
fi
|
|
|
|
chmod +x "$launcher_dir/davinci-resolve"
|
|
|
|
# Create Rusticl fallback launcher (davincibox -c flag equivalent)
|
|
# Use this if ROCm OpenCL doesn't work with your GPU
|
|
cat > "$launcher_dir/davinci-resolve-rusticl" << 'EOF'
|
|
#!/bin/bash
|
|
# DaVinci Resolve Launcher - Rusticl OpenCL Fallback
|
|
# Use this if ROCm doesn't work with your GPU (davincibox -c equivalent)
|
|
# Requires: opencl-rusticl-mesa package
|
|
|
|
export QT_QPA_PLATFORM=xcb
|
|
export QT_AUTO_SCREEN_SCALE_FACTOR=1
|
|
|
|
# Rusticl configuration (Mesa OpenCL implementation)
|
|
export RUSTICL_ENABLE=radeonsi,iris,nouveau
|
|
export OCL_ICD_VENDORS=rusticl.icd
|
|
|
|
ulimit -n 65535 2>/dev/null
|
|
exec /opt/resolve/bin/resolve "$@"
|
|
EOF
|
|
chmod +x "$launcher_dir/davinci-resolve-rusticl"
|
|
info "Created Rusticl fallback launcher: davinci-resolve-rusticl"
|
|
|
|
# Also create a version that forces integrated GPU (useful for testing/power saving)
|
|
if [[ "$SCAN_IS_HYBRID" == true ]]; then
|
|
cat > "$launcher_dir/davinci-resolve-igpu" << 'EOF'
|
|
#!/bin/bash
|
|
# DaVinci Resolve Launcher - Force Integrated GPU
|
|
# Use this for power saving or if discrete GPU causes issues
|
|
|
|
export QT_QPA_PLATFORM=xcb
|
|
export QT_AUTO_SCREEN_SCALE_FACTOR=1
|
|
export DRI_PRIME=0
|
|
|
|
ulimit -n 65535 2>/dev/null
|
|
exec /opt/resolve/bin/resolve "$@"
|
|
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
|
|
|
|
success "Launcher created."
|
|
|
|
echo ""
|
|
info "Available launchers:"
|
|
echo " davinci-resolve - Main launcher (default)"
|
|
echo " davinci-resolve-rusticl - Rusticl OpenCL fallback (if ROCm fails)"
|
|
|
|
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 ""
|
|
info "If Resolve fails to use GPU, try: davinci-resolve-rusticl"
|
|
echo " (requires: sudo pacman -S opencl-rusticl-mesa)"
|
|
}
|
|
|
|
configure_hyprland() {
|
|
if [[ "$SCAN_HYPRLAND_INSTALLED" != true ]]; then
|
|
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 ""
|
|
cat << 'EOF'
|
|
windowrulev2 = tag +drpopup, class:^(resolve)$, floating:1
|
|
windowrulev2 = stayfocused, tag:drpopup
|
|
windowrulev2 = noborder, tag:drpopup
|
|
windowrulev2 = opaque, 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)"
|
|
|
|
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
|
|
EOF
|
|
|
|
success "Hyprland rules added."
|
|
info "Reload with: hyprctl reload"
|
|
}
|
|
|
|
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)
|
|
|
|
convert_file() {
|
|
local input="$1"
|
|
local output="${2:-${input%.*}_dnxhr.mov}"
|
|
echo "Converting: $input -> $output"
|
|
ffmpeg -i "$input" -c:v dnxhd -profile:v dnxhr_hq -pix_fmt yuv422p -c:a pcm_s16le -y "$output"
|
|
echo "Done: $output"
|
|
}
|
|
|
|
[[ $# -eq 0 ]] && { echo "Usage: resolve-convert input.mp4 [output.mov]"; exit 1; }
|
|
|
|
if [[ $# -eq 2 && ! "$2" =~ \.(mp4|mkv|avi|webm)$ ]]; then
|
|
convert_file "$1" "$2"
|
|
else
|
|
for f in "$@"; do [[ -f "$f" ]] && convert_file "$f"; done
|
|
fi
|
|
EOF
|
|
|
|
chmod +x "$HOME/.local/bin/resolve-convert"
|
|
success "Created: resolve-convert"
|
|
}
|
|
|
|
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"
|
|
}
|
|
|
|
print_summary() {
|
|
echo ""
|
|
echo "============================================================"
|
|
echo -e "${GREEN} Installation Complete!${NC}"
|
|
echo "============================================================"
|
|
echo ""
|
|
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"
|
|
fi
|
|
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 ""
|
|
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)"
|
|
echo ""
|
|
fi
|
|
echo "============================================================"
|
|
}
|
|
|
|
# =============================================================================
|
|
# MAIN
|
|
# =============================================================================
|
|
|
|
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 "============================================================"
|
|
echo ""
|
|
|
|
# Run system scan
|
|
run_system_scan
|
|
display_scan_results
|
|
|
|
# Analyze and check for blockers
|
|
if ! analyze_scan_results; then
|
|
echo ""
|
|
read -p "Continue despite issues? [y/N] " -n 1 -r
|
|
echo
|
|
[[ ! $REPLY =~ ^[Yy]$ ]] && exit 1
|
|
fi
|
|
|
|
# Check AUR helper
|
|
if [[ -z "$SCAN_AUR_HELPER" ]]; then
|
|
error "No AUR helper found. Install yay or paru first."
|
|
fi
|
|
|
|
# Build package list
|
|
build_package_list
|
|
|
|
echo ""
|
|
read -p "Proceed with installation? [Y/n] " -n 1 -r
|
|
echo
|
|
[[ $REPLY =~ ^[Nn]$ ]] && exit 0
|
|
|
|
# Configure user groups for GPU access
|
|
configure_user_groups
|
|
|
|
# Install
|
|
install_pacman_packages
|
|
install_aur_packages
|
|
install_davinci_resolve
|
|
apply_patchelf_fix
|
|
disable_opencl_decoders
|
|
setup_studio_usb_dongle
|
|
create_launcher
|
|
configure_hyprland
|
|
create_conversion_script
|
|
install_diagnostics
|
|
|
|
print_summary
|
|
}
|
|
|
|
main "$@"
|