Refactor VAAPI passthrough to external script
Some checks failed
Bump build.func Revision / bump-revision (push) Has been cancelled
Some checks failed
Bump build.func Revision / bump-revision (push) Has been cancelled
Replaces the inlined VAAPI passthrough logic in misc/build.func with calls to an external passthrough.func script, streamlining and centralizing hardware passthrough handling. Adds a new misc/passthrough.func file and introduces a hwaccel_setup_in_ct helper in misc/tools.func for hardware acceleration setup inside containers.
This commit is contained in:
parent
1f8a76e8e2
commit
8aae603267
318
misc/build.func
318
misc/build.func
@ -2199,320 +2199,10 @@ lxc.mount.entry: /dev/ttyACM1 dev/ttyACM1 none bind,optional,create=
|
|||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# VAAPI passthrough for privileged containers or known apps
|
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/passthrough.func)
|
||||||
VAAPI_APPS=(
|
usb_handle_passthrough "$CTID" "$CT_TYPE"
|
||||||
"immich" "Channels" "Emby" "ErsatzTV" "Frigate" "Jellyfin"
|
vaapi_handle_passthrough "$CTID" "$CT_TYPE" "$APP"
|
||||||
"Plex" "Scrypted" "Tdarr" "Unmanic" "Ollama" "FileFlows"
|
nvidia_handle_passthrough "$CTID" "$CT_TYPE" "$APP"
|
||||||
"Open WebUI" "Debian" "Tunarr"
|
|
||||||
)
|
|
||||||
|
|
||||||
is_vaapi_app=false
|
|
||||||
for vaapi_app in "${VAAPI_APPS[@]}"; do
|
|
||||||
if [[ "$APP" == "$vaapi_app" ]]; then
|
|
||||||
is_vaapi_app=true
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ "$CT_TYPE" == "0" || "$is_vaapi_app" == "true" ]]; then
|
|
||||||
# Standard: don’t include fb0 unless explicitly wanted
|
|
||||||
vaapi_select_and_apply "$CTID" "$CT_TYPE" || msg_warn "VAAPI setup skipped/partial."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# --- VAAPI: helper to resolve GID dynamically
|
|
||||||
_vaapi_gid() {
|
|
||||||
local g="$1" gid
|
|
||||||
gid="$(getent group "$g" | cut -d: -f3)"
|
|
||||||
if [[ -z "$gid" ]]; then
|
|
||||||
case "$g" in
|
|
||||||
video) echo 44 ;; # default fallback
|
|
||||||
render) echo 104 ;; # default fallback
|
|
||||||
*) echo 44 ;;
|
|
||||||
esac
|
|
||||||
else
|
|
||||||
echo "$gid"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# --- VAAPI: detect devices, dedupe, pretty labels
|
|
||||||
_vaapi_pairs() {
|
|
||||||
local seen=() by real id idx card pci pci_info name
|
|
||||||
shopt -s nullglob
|
|
||||||
for by in /dev/dri/by-path/*-render /dev/dri/renderD*; do
|
|
||||||
[[ -e "$by" ]] || continue
|
|
||||||
real="$(readlink -f "$by" || true)"
|
|
||||||
[[ -e "$real" ]] || continue
|
|
||||||
id="$(basename "$real")"
|
|
||||||
if [[ " ${seen[*]} " == *" $id "* ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
seen+=("$id")
|
|
||||||
|
|
||||||
idx="${id#renderD}"
|
|
||||||
if [[ "$idx" =~ ^[0-9]+$ ]]; then
|
|
||||||
idx=$((idx - 128))
|
|
||||||
else
|
|
||||||
idx=0
|
|
||||||
fi
|
|
||||||
card="/dev/dri/card${idx}"
|
|
||||||
[[ -e "$card" ]] || card=""
|
|
||||||
|
|
||||||
if [[ "$by" == *"/by-path/"* ]]; then
|
|
||||||
pci="$(basename "$by" | sed -E 's/^pci-([0-9a-fA-F:.]+)-render/\1/')"
|
|
||||||
pci_info="$(lspci -nn 2>/dev/null | grep -i "${pci#0000:}" || true)"
|
|
||||||
name="${pci_info#*: }"
|
|
||||||
[[ -z "$name" ]] && name="GPU ${pci}"
|
|
||||||
else
|
|
||||||
name="DRM $(basename "$real")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
label="$(basename "$real")"
|
|
||||||
[[ -n "$card" ]] && label+=" + $(basename "$card")"
|
|
||||||
label+=" – ${name}"
|
|
||||||
|
|
||||||
printf "%s:%s\t%s\n" "$real" "$card" "$label"
|
|
||||||
done
|
|
||||||
shopt -u nullglob
|
|
||||||
}
|
|
||||||
|
|
||||||
# --- VAAPI: whiptail dimension helper
|
|
||||||
_whiptail_dims() {
|
|
||||||
local n="$1" L="$2"
|
|
||||||
local maxW=$((L + 8))
|
|
||||||
((maxW < 70)) && maxW=70
|
|
||||||
((maxW > 100)) && maxW=100
|
|
||||||
local H=$((10 + n * 2))
|
|
||||||
((H > 22)) && H=22
|
|
||||||
echo "$H $maxW"
|
|
||||||
}
|
|
||||||
|
|
||||||
# --- VAAPI: main selector and config writer
|
|
||||||
vaapi_select_and_apply() {
|
|
||||||
local CTID="$1" CTTYPE="$2"
|
|
||||||
local LXC_CONFIG="/etc/pve/lxc/${CTID}.conf"
|
|
||||||
|
|
||||||
local pairs=() items=() maxlen=0 n h w
|
|
||||||
mapfile -t pairs < <(_vaapi_pairs)
|
|
||||||
|
|
||||||
if ((${#pairs[@]} == 0)); then
|
|
||||||
msg_warn "No VAAPI devices detected – skipping passthrough."
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
for p in "${pairs[@]}"; do
|
|
||||||
local devs="${p%%$'\t'*}"
|
|
||||||
local label="${p#*$'\t'}"
|
|
||||||
items+=("$devs" "$label" "OFF")
|
|
||||||
((${#label} > maxlen)) && maxlen=${#label}
|
|
||||||
done
|
|
||||||
n=$((${#items[@]} / 3))
|
|
||||||
read -r h w < <(_whiptail_dims "$n" "$maxlen")
|
|
||||||
|
|
||||||
if [[ "$CTTYPE" == "0" ]]; then
|
|
||||||
whiptail --title "VAAPI passthrough" --msgbox "\
|
|
||||||
VAAPI passthrough will be enabled.
|
|
||||||
|
|
||||||
• Privileged CT: full DRM access
|
|
||||||
• You may need to install drivers inside the container
|
|
||||||
(e.g. intel-media-driver, vainfo)." 12 "$w"
|
|
||||||
else
|
|
||||||
whiptail --title "VAAPI passthrough (unprivileged)" --msgbox "\
|
|
||||||
Unprivileged CT: VAAPI may be limited.
|
|
||||||
|
|
||||||
If it fails, consider using a privileged container.
|
|
||||||
You may still need drivers inside the CT." 12 "$w"
|
|
||||||
fi
|
|
||||||
|
|
||||||
local SELECTED
|
|
||||||
SELECTED="$(
|
|
||||||
whiptail --title "VAAPI Device Selection" \
|
|
||||||
--checklist "Select GPU / VAAPI device(s) to passthrough:" "$h" "$w" "$((n > 6 ? 6 : n))" \
|
|
||||||
"${items[@]}" 3>&1 1>&2 2>&3
|
|
||||||
)" || {
|
|
||||||
msg_warn "VAAPI selection cancelled."
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
[[ -z "$SELECTED" ]] && {
|
|
||||||
msg_warn "No devices selected – skipping passthrough."
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
local DID_MOUNT_DRI=0 idx=0
|
|
||||||
for dev in $SELECTED; do
|
|
||||||
dev="${dev%\"}"
|
|
||||||
dev="${dev#\"}"
|
|
||||||
IFS=":" read -r path card <<<"$dev"
|
|
||||||
for d in "$path" "$card"; do
|
|
||||||
[[ -n "$d" && -e "$d" ]] || continue
|
|
||||||
if [[ "$CTTYPE" == "0" ]]; then
|
|
||||||
if [[ "$DID_MOUNT_DRI" -eq 0 && -d /dev/dri ]]; then
|
|
||||||
echo "lxc.mount.entry: /dev/dri /dev/dri none bind,optional,create=dir" >>"$LXC_CONFIG"
|
|
||||||
DID_MOUNT_DRI=1
|
|
||||||
fi
|
|
||||||
if mm=$(stat -c '%t:%T' "$d" 2>/dev/null | awk -F: '{printf "%d:%d","0x"$1,"0x"$2}'); then
|
|
||||||
echo "lxc.cgroup2.devices.allow: c $mm rwm" >>"$LXC_CONFIG"
|
|
||||||
echo "lxc.mount.entry: $d $d none bind,optional,create=file" >>"$LXC_CONFIG"
|
|
||||||
else
|
|
||||||
msg_warn "Could not stat $d – skipping."
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
local gid
|
|
||||||
if [[ "$d" =~ renderD ]]; then
|
|
||||||
gid="$(_vaapi_gid render)"
|
|
||||||
else
|
|
||||||
gid="$(_vaapi_gid video)"
|
|
||||||
fi
|
|
||||||
echo "dev${idx}: $d,gid=${gid}" >>"$LXC_CONFIG"
|
|
||||||
idx=$((idx + 1))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
# Fallback if card0/card1 flip causes missing nodes
|
|
||||||
if [[ "$CTTYPE" == "0" ]]; then
|
|
||||||
cat <<'EOF' >>"$LXC_CONFIG"
|
|
||||||
# VAAPI fallback: bind /dev/dri if specific nodes are missing
|
|
||||||
lxc.mount.entry: /dev/dri /dev/dri none bind,optional,create=dir
|
|
||||||
lxc.cgroup2.devices.allow: c 226:* rwm
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# if [[ "$CT_TYPE" == "0" || "$is_vaapi_app" == "true" ]]; then
|
|
||||||
# VAAPI_DEVICES=()
|
|
||||||
# SINGLE_VAAPI_DEVICE=""
|
|
||||||
# seen_ids=()
|
|
||||||
|
|
||||||
# for bypath in /dev/dri/by-path/*-render /dev/dri/renderD*; do
|
|
||||||
# [[ -e "$bypath" ]] || continue
|
|
||||||
# dev_render=$(readlink -f "$bypath") || continue
|
|
||||||
# id=$(basename "$dev_render")
|
|
||||||
# [[ " ${seen_ids[*]} " == *" $id "* ]] && continue
|
|
||||||
# seen_ids+=("$id")
|
|
||||||
|
|
||||||
# card_index="${id#renderD}"
|
|
||||||
# card="/dev/dri/card${card_index}"
|
|
||||||
# combo_devices=("$dev_render")
|
|
||||||
# if [[ "${#combo_devices[@]}" -eq 1 && -e /dev/dri/card0 ]]; then
|
|
||||||
# combo_devices+=("/dev/dri/card0")
|
|
||||||
# fi
|
|
||||||
# #echo "combo_devices=${combo_devices[*]}"
|
|
||||||
|
|
||||||
# pci_addr=$(basename "$bypath" | cut -d- -f1 --complement | sed 's/-render//' || true)
|
|
||||||
# pci_info=$(lspci -nn | grep "${pci_addr#0000:}" || true)
|
|
||||||
# name="${pci_info#*: }"
|
|
||||||
# [[ -z "$name" ]] && name="Unknown GPU ($pci_addr)"
|
|
||||||
|
|
||||||
# label="$(basename "$dev_render")"
|
|
||||||
# [[ -e "$card" ]] && label+=" + $(basename "$card")"
|
|
||||||
# label+=" – $name"
|
|
||||||
# msg_debug "[VAAPI DEBUG] Adding VAAPI combo: ${combo_devices[*]} ($label)"
|
|
||||||
|
|
||||||
# VAAPI_DEVICES+=("$(
|
|
||||||
# IFS=:
|
|
||||||
# echo "${combo_devices[*]}"
|
|
||||||
# )" "$label" "OFF")
|
|
||||||
# done
|
|
||||||
|
|
||||||
# [[ -e /dev/fb0 ]] && VAAPI_DEVICES+=("/dev/fb0" "fb0 - Framebuffer" "OFF")
|
|
||||||
|
|
||||||
# GID_VIDEO=$(getent group video | cut -d: -f3)
|
|
||||||
# GID_RENDER=$(getent group render | cut -d: -f3)
|
|
||||||
# [[ -z "$GID_VIDEO" ]] && GID_VIDEO=44 && msg_warn "'video' group not found, falling back to GID 44"
|
|
||||||
# [[ -z "$GID_RENDER" ]] && GID_RENDER=104 && msg_warn "'render' group not found, falling back to GID 104"
|
|
||||||
|
|
||||||
# if [[ "${#VAAPI_DEVICES[@]}" -eq 0 ]]; then
|
|
||||||
# msg_warn "No VAAPI-compatible devices found."
|
|
||||||
# elif [[ "${#VAAPI_DEVICES[@]}" -eq 3 ]]; then
|
|
||||||
# #msg_info "Only one VAAPI-compatible device found – enabling passthrough."
|
|
||||||
|
|
||||||
# IFS=":" read -ra devices <<<"${VAAPI_DEVICES[0]//\"/}"
|
|
||||||
# IDX=0
|
|
||||||
# DID_MOUNT_DRI=0
|
|
||||||
|
|
||||||
# for d in "${devices[@]}"; do
|
|
||||||
# if [[ "$CT_TYPE" == "0" ]]; then
|
|
||||||
# if [[ "$DID_MOUNT_DRI" -eq 0 && -d /dev/dri ]]; then
|
|
||||||
# echo "lxc.mount.entry: /dev/dri /dev/dri none bind,optional,create=dir" >>"$LXC_CONFIG"
|
|
||||||
# DID_MOUNT_DRI=1
|
|
||||||
# fi
|
|
||||||
# if ! major_minor=$(stat -c '%t:%T' "$d" 2>/dev/null | awk -F: '{ printf "%d:%d", "0x"$1, "0x"$2 }'); then
|
|
||||||
# msg_warn "Could not stat $d – skipping."
|
|
||||||
# continue
|
|
||||||
# fi
|
|
||||||
# echo "lxc.cgroup2.devices.allow: c $major_minor rwm" >>"$LXC_CONFIG"
|
|
||||||
# echo "lxc.mount.entry: $d $d none bind,optional,create=file" >>"$LXC_CONFIG"
|
|
||||||
# else
|
|
||||||
# GID=$([[ "$d" =~ render ]] && echo "$GID_RENDER" || echo "$GID_VIDEO")
|
|
||||||
# echo "dev${IDX}: $d,gid=${GID}" >>"$LXC_CONFIG"
|
|
||||||
# IDX=$((IDX + 1))
|
|
||||||
# fi
|
|
||||||
# done
|
|
||||||
|
|
||||||
# else
|
|
||||||
# if [[ "$CT_TYPE" == "0" ]]; then
|
|
||||||
# whiptail --title "VAAPI passthrough" --msgbox "\
|
|
||||||
# ✅ VAAPI passthrough has been enabled
|
|
||||||
|
|
||||||
# GPU hardware acceleration will be available inside the container
|
|
||||||
# (e.g., for Jellyfin, Plex, Frigate, etc.)
|
|
||||||
|
|
||||||
# ℹ️ Note: You may need to install drivers manually inside the container,
|
|
||||||
# such as 'intel-media-driver', 'libva2', or 'vainfo'." 15 74
|
|
||||||
# else
|
|
||||||
# whiptail --title "VAAPI passthrough (limited)" --msgbox "\
|
|
||||||
# ⚠️ VAAPI passthrough in unprivileged containers may be limited
|
|
||||||
|
|
||||||
# Some drivers (e.g., iHD) require privileged access to DRM subsystems.
|
|
||||||
# If VAAPI fails, consider switching to a privileged container.
|
|
||||||
|
|
||||||
# ℹ️ Note: You may need to install drivers manually inside the container,
|
|
||||||
# such as 'intel-media-driver', 'libva2', or 'vainfo'." 15 74
|
|
||||||
# fi
|
|
||||||
|
|
||||||
# SELECTED_DEVICES=$(whiptail --title "VAAPI Device Selection" \
|
|
||||||
# --checklist "Select VAAPI device(s) / GPU(s) to passthrough:" 20 100 6 \
|
|
||||||
# "${VAAPI_DEVICES[@]}" 3>&1 1>&2 2>&3)
|
|
||||||
|
|
||||||
# if [[ $? -ne 0 ]]; then
|
|
||||||
# exit_script
|
|
||||||
# msg_error "VAAPI passthrough selection cancelled by user."
|
|
||||||
# fi
|
|
||||||
|
|
||||||
# if [[ -n "$SELECTED_DEVICES" ]]; then
|
|
||||||
# IDX=0
|
|
||||||
# DID_MOUNT_DRI=0
|
|
||||||
# for dev in $SELECTED_DEVICES; do
|
|
||||||
# dev="${dev%\"}"
|
|
||||||
# dev="${dev#\"}" # strip quotes
|
|
||||||
# IFS=":" read -ra devices <<<"$dev"
|
|
||||||
# msg_debug "[VAAPI DEBUG] Autopassthrough for devices: ${devices[*]}"
|
|
||||||
# for d in "${devices[@]}"; do
|
|
||||||
# if [[ "$CT_TYPE" == "0" ]]; then
|
|
||||||
# if [[ "$DID_MOUNT_DRI" -eq 0 && -d /dev/dri ]]; then
|
|
||||||
# echo "lxc.mount.entry: /dev/dri /dev/dri none bind,optional,create=dir" >>"$LXC_CONFIG"
|
|
||||||
# DID_MOUNT_DRI=1
|
|
||||||
# fi
|
|
||||||
# if ! major_minor=$(stat -c '%t:%T' "$d" 2>/dev/null | awk -F: '{ printf "%d:%d", "0x"$1, "0x"$2 }'); then
|
|
||||||
# msg_warn "Could not stat $d – skipping."
|
|
||||||
# continue
|
|
||||||
# fi
|
|
||||||
# echo "lxc.cgroup2.devices.allow: c $major_minor rwm" >>"$LXC_CONFIG"
|
|
||||||
# echo "lxc.mount.entry: $d $d none bind,optional,create=file" >>"$LXC_CONFIG"
|
|
||||||
# else
|
|
||||||
# GID=$([[ "$d" =~ render ]] && echo "$GID_RENDER" || echo "$GID_VIDEO")
|
|
||||||
|
|
||||||
# echo "dev${IDX}: $d,gid=${GID}" >>"$LXC_CONFIG"
|
|
||||||
# IDX=$((IDX + 1))
|
|
||||||
# fi
|
|
||||||
# done
|
|
||||||
# done
|
|
||||||
# else
|
|
||||||
# msg_warn "No VAAPI devices selected – passthrough skipped."
|
|
||||||
# fi
|
|
||||||
# fi
|
|
||||||
# fi
|
|
||||||
|
|
||||||
# TUN device passthrough
|
# TUN device passthrough
|
||||||
if [ "$ENABLE_TUN" == "yes" ]; then
|
if [ "$ENABLE_TUN" == "yes" ]; then
|
||||||
|
0
misc/passthrough.func
Normal file
0
misc/passthrough.func
Normal file
@ -2091,3 +2091,80 @@ check_for_gh_release() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Hardware acceleration setup inside container
|
||||||
|
# Works with: Debian 12 (bookworm), Debian 13 (trixie), Ubuntu 24.04 (noble)
|
||||||
|
# Usage: hwaccel_setup_in_ct <CTTYPE 0|1> [--nonfree-intel]
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
hwaccel_setup_in_ct() {
|
||||||
|
local CTTYPE="$1" NONFREE=0
|
||||||
|
[[ "$2" == "--nonfree-intel" ]] && NONFREE=1
|
||||||
|
|
||||||
|
# Detect OS info inside the container
|
||||||
|
local ID VERSION_CODENAME
|
||||||
|
if [[ -r /etc/os-release ]]; then
|
||||||
|
. /etc/os-release
|
||||||
|
fi
|
||||||
|
ID="${ID:-debian}"
|
||||||
|
VERSION_CODENAME="${VERSION_CODENAME:-bookworm}"
|
||||||
|
|
||||||
|
msg_info "Setting up hardware acceleration for ${ID^} ($VERSION_CODENAME)"
|
||||||
|
|
||||||
|
case "$ID" in
|
||||||
|
debian | ubuntu)
|
||||||
|
if ((NONFREE)) && [[ "$VERSION_CODENAME" =~ (trixie|noble) ]]; then
|
||||||
|
# Debian 13 / Ubuntu 24.04 → non-free Intel driver
|
||||||
|
cat >/etc/apt/sources.list.d/non-free.sources <<'SRC'
|
||||||
|
Types: deb deb-src
|
||||||
|
URIs: http://deb.debian.org/debian
|
||||||
|
Suites: trixie
|
||||||
|
Components: non-free non-free-firmware
|
||||||
|
|
||||||
|
Types: deb deb-src
|
||||||
|
URIs: http://deb.debian.org/debian-security
|
||||||
|
Suites: trixie-security
|
||||||
|
Components: non-free non-free-firmware
|
||||||
|
|
||||||
|
Types: deb deb-src
|
||||||
|
URIs: http://deb.debian.org/debian
|
||||||
|
Suites: trixie-updates
|
||||||
|
Components: non-free non-free-firmware
|
||||||
|
SRC
|
||||||
|
|
||||||
|
$STD apt-get update
|
||||||
|
$STD apt-get install -y \
|
||||||
|
intel-media-va-driver-non-free \
|
||||||
|
ocl-icd-libopencl1 \
|
||||||
|
mesa-opencl-icd \
|
||||||
|
mesa-va-drivers \
|
||||||
|
libvpl2 \
|
||||||
|
vainfo \
|
||||||
|
intel-gpu-tools
|
||||||
|
else
|
||||||
|
# Debian 12 (bookworm) and fallback for Debian 13/Ubuntu 24.04 without non-free
|
||||||
|
$STD apt-get update
|
||||||
|
$STD apt-get install -y \
|
||||||
|
va-driver-all \
|
||||||
|
ocl-icd-libopencl1 \
|
||||||
|
mesa-opencl-icd \
|
||||||
|
mesa-va-drivers \
|
||||||
|
vainfo \
|
||||||
|
intel-gpu-tools
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
msg_warn "Unsupported distribution ($ID $VERSION_CODENAME) – skipping HW accel setup"
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Add current user to video/render groups (only for privileged CTs)
|
||||||
|
if [[ "$CTTYPE" == "0" ]]; then
|
||||||
|
$STD adduser "$(id -un)" video || true
|
||||||
|
$STD adduser "$(id -un)" render || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_ok "Hardware acceleration is ready"
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user