fix(installer): improve GPU detection to avoid false positives (#254)
* fix(installer): improve GPU detection to avoid false positives - Filter out software renderers (llvmpipe, swiftshader, lavapipe, etc.) when checking Vulkan compatibility - these are CPU implementations and should not affect hardware GPU detection - Skip Vulkan compatibility check for NVIDIA GPUs since they use CUDA instead of Vulkan for acceleration - Reorder backend priority: CUDA > Vulkan > CPU - Only show incompatible GPU warning for actual Vulkan-based GPUs (AMD/Intel) that lack VK_KHR_16bit_storage support Fixes issue where RTX 5080 + llvmpipe combination was incorrectly flagged as incompatible due to llvmpipe lacking 16-bit storage support. * fix(installer): recommend GPU even without dev libraries installed The installer installs dev libraries (libvulkan-dev, glslc) in install_system_dependencies(), which runs AFTER the backend selection. So we should recommend GPU if there's a compatible GPU regardless of whether dev libraries are currently installed. Changes: - NVIDIA GPU detected → recommend CUDA (even without nvcc) - Vulkan-compatible GPU → recommend Vulkan (even without libvulkan-dev) - Only fall back to CPU if no compatible GPU detected or GPU is genuinely incompatible (old Intel Gen7)
This commit is contained in:
+103
-44
@@ -483,8 +483,12 @@ detect_vulkan() {
|
||||
# These GPUs will fail with "device does not support 16-bit storage" error
|
||||
# Affected: Intel Gen7 and older (Ivy Bridge, Haswell, Sandy Bridge)
|
||||
# See: https://github.com/jatinkrmalik/vocalinux/issues/238
|
||||
#
|
||||
# IMPORTANT: This check filters out software renderers (llvmpipe, etc.) and only
|
||||
# evaluates real hardware GPUs. Modern AMD, Intel (Gen8+), and NVIDIA GPUs all
|
||||
# support VK_KHR_16bit_storage, so this mainly catches very old Intel Gen7 GPUs.
|
||||
check_vulkan_gpu_compatibility() {
|
||||
# List of known incompatible GPU patterns
|
||||
# List of known incompatible GPU patterns (old Intel Gen7 and older)
|
||||
local INCOMPATIBLE_PATTERNS=(
|
||||
"Ivy Bridge"
|
||||
"Haswell"
|
||||
@@ -500,55 +504,95 @@ check_vulkan_gpu_compatibility() {
|
||||
"SNB"
|
||||
)
|
||||
|
||||
# Software renderers and virtual devices to skip (not real hardware GPUs)
|
||||
# These are CPU-based implementations that shouldn't affect compatibility detection
|
||||
local SOFTWARE_RENDERER_PATTERNS=(
|
||||
"llvmpipe"
|
||||
"swiftshader"
|
||||
"lavapipe"
|
||||
"zink"
|
||||
"virtio"
|
||||
"venus"
|
||||
)
|
||||
|
||||
# Check if vulkaninfo is available
|
||||
if ! command -v vulkaninfo >/dev/null 2>&1; then
|
||||
echo "unknown:vulkaninfo not available"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Get all device names from vulkaninfo
|
||||
local DEVICE_NAMES_RAW
|
||||
DEVICE_NAMES_RAW=$(vulkaninfo --summary 2>/dev/null | awk -F'=' '/deviceName/ {gsub(/^[ \t]+|[ \t]+$/, "", $2); if ($2 != "") print $2}')
|
||||
|
||||
local DEVICE_NAMES_LABEL=""
|
||||
# Separate hardware GPUs from software renderers
|
||||
local HARDWARE_GPUS=""
|
||||
local HARDWARE_GPU_COUNT=0
|
||||
while IFS= read -r device_name; do
|
||||
[ -z "$device_name" ] && continue
|
||||
if [ -n "$DEVICE_NAMES_LABEL" ]; then
|
||||
DEVICE_NAMES_LABEL="${DEVICE_NAMES_LABEL}, ${device_name}"
|
||||
else
|
||||
DEVICE_NAMES_LABEL="$device_name"
|
||||
|
||||
local is_software=false
|
||||
for pattern in "${SOFTWARE_RENDERER_PATTERNS[@]}"; do
|
||||
if echo "$device_name" | grep -iq "$pattern"; then
|
||||
is_software=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$is_software" = false ]; then
|
||||
if [ -n "$HARDWARE_GPUS" ]; then
|
||||
HARDWARE_GPUS="${HARDWARE_GPUS}, ${device_name}"
|
||||
else
|
||||
HARDWARE_GPUS="$device_name"
|
||||
fi
|
||||
((HARDWARE_GPU_COUNT++))
|
||||
fi
|
||||
done <<< "$DEVICE_NAMES_RAW"
|
||||
|
||||
# If no hardware GPUs found, we can't determine compatibility
|
||||
if [ -z "$HARDWARE_GPUS" ]; then
|
||||
echo "unknown:No hardware GPU found (only software renderers)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Get Vulkan features and check for VK_KHR_16bit_storage
|
||||
# Modern GPUs (AMD, Intel Gen8+, NVIDIA) all support this extension
|
||||
local FEATURES_OUTPUT
|
||||
FEATURES_OUTPUT=$(vulkaninfo --features 2>/dev/null)
|
||||
|
||||
if [ -n "$FEATURES_OUTPUT" ]; then
|
||||
if echo "$FEATURES_OUTPUT" | grep -Eq "VK_KHR_16bit_storage|storageBuffer16BitAccess[[:space:]]*=[[:space:]]*true|uniformAndStorageBuffer16BitAccess[[:space:]]*=[[:space:]]*true|storagePushConstant16[[:space:]]*=[[:space:]]*true"; then
|
||||
if [ -z "$DEVICE_NAMES_LABEL" ]; then
|
||||
DEVICE_NAMES_LABEL="Vulkan GPU (VK_KHR_16bit_storage)"
|
||||
fi
|
||||
echo "compatible:${DEVICE_NAMES_LABEL}"
|
||||
# Check for VK_KHR_16bit_storage extension or equivalent features
|
||||
if echo "$FEATURES_OUTPUT" | grep -q "VK_KHR_16bit_storage"; then
|
||||
echo "compatible:${HARDWARE_GPUS}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ -z "$DEVICE_NAMES_LABEL" ]; then
|
||||
DEVICE_NAMES_LABEL="Vulkan GPU"
|
||||
# Alternative: check for 16-bit storage features directly
|
||||
if echo "$FEATURES_OUTPUT" | grep -Eq "storageBuffer16BitAccess[[:space:]]*=[[:space:]]*true|uniformAndStorageBuffer16BitAccess[[:space:]]*=[[:space:]]*true"; then
|
||||
echo "compatible:${HARDWARE_GPUS}"
|
||||
return 0
|
||||
fi
|
||||
echo "incompatible:${DEVICE_NAMES_LABEL} (missing VK_KHR_16bit_storage)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$DEVICE_NAMES_RAW" ]; then
|
||||
echo "unknown:Could not detect GPU name"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# If Vulkan features check didn't confirm support, check against known incompatible patterns
|
||||
# This handles systems where vulkaninfo --features doesn't show the extension
|
||||
local INCOMPATIBLE_GPUS=""
|
||||
local HAS_COMPATIBLE_GPU=false
|
||||
local INCOMPATIBLE_LABEL=""
|
||||
|
||||
while IFS= read -r device_name; do
|
||||
[ -z "$device_name" ] && continue
|
||||
|
||||
# Skip software renderers
|
||||
local is_software=false
|
||||
for pattern in "${SOFTWARE_RENDERER_PATTERNS[@]}"; do
|
||||
if echo "$device_name" | grep -iq "$pattern"; then
|
||||
is_software=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
[ "$is_software" = true ] && continue
|
||||
|
||||
# Check against known incompatible patterns
|
||||
local is_incompatible=false
|
||||
for pattern in "${INCOMPATIBLE_PATTERNS[@]}"; do
|
||||
if echo "$device_name" | grep -iq "$pattern"; then
|
||||
@@ -558,23 +602,24 @@ check_vulkan_gpu_compatibility() {
|
||||
done
|
||||
|
||||
if [ "$is_incompatible" = true ]; then
|
||||
if [ -n "$INCOMPATIBLE_LABEL" ]; then
|
||||
INCOMPATIBLE_LABEL="${INCOMPATIBLE_LABEL}, ${device_name}"
|
||||
if [ -n "$INCOMPATIBLE_GPUS" ]; then
|
||||
INCOMPATIBLE_GPUS="${INCOMPATIBLE_GPUS}, ${device_name}"
|
||||
else
|
||||
INCOMPATIBLE_LABEL="$device_name"
|
||||
INCOMPATIBLE_GPUS="$device_name"
|
||||
fi
|
||||
else
|
||||
# GPU doesn't match known incompatible patterns - assume compatible
|
||||
HAS_COMPATIBLE_GPU=true
|
||||
fi
|
||||
done <<< "$DEVICE_NAMES_RAW"
|
||||
|
||||
if [ "$HAS_COMPATIBLE_GPU" = true ]; then
|
||||
echo "compatible:${DEVICE_NAMES_LABEL}"
|
||||
echo "compatible:${HARDWARE_GPUS}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ -n "$INCOMPATIBLE_LABEL" ]; then
|
||||
echo "incompatible:${INCOMPATIBLE_LABEL}"
|
||||
if [ -n "$INCOMPATIBLE_GPUS" ]; then
|
||||
echo "incompatible:${INCOMPATIBLE_GPUS}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -600,41 +645,55 @@ detect_whispercpp_backends() {
|
||||
fi
|
||||
|
||||
# Check Vulkan GPU compatibility (Gen7 and older Intel GPUs lack 16-bit storage support)
|
||||
# Skip this check for NVIDIA GPUs since they use CUDA, not Vulkan
|
||||
local VULKAN_COMPATIBLE="unknown"
|
||||
local VULKAN_COMPAT_REASON=""
|
||||
if [[ "$HAS_VULKAN" == "yes" ]]; then
|
||||
if [[ "$HAS_VULKAN" == "yes" && "$HAS_NVIDIA_GPU" != "yes" ]]; then
|
||||
local COMPAT_RESULT
|
||||
COMPAT_RESULT=$(check_vulkan_gpu_compatibility)
|
||||
VULKAN_COMPATIBLE=$(echo "$COMPAT_RESULT" | cut -d':' -f1)
|
||||
VULKAN_COMPAT_REASON=$(echo "$COMPAT_RESULT" | cut -d':' -f2-)
|
||||
elif [[ "$HAS_NVIDIA_GPU" == "yes" ]]; then
|
||||
# NVIDIA GPUs use CUDA, so Vulkan compatibility is irrelevant
|
||||
VULKAN_COMPATIBLE="not_applicable"
|
||||
VULKAN_COMPAT_REASON="NVIDIA GPU uses CUDA"
|
||||
fi
|
||||
|
||||
# Determine recommendation
|
||||
# Determine recommendation (Priority: CUDA > Vulkan > CPU)
|
||||
# IMPORTANT: The installer WILL install dev libraries (libvulkan-dev, glslc, CUDA) later,
|
||||
# so we recommend GPU if there's a compatible GPU regardless of current library status.
|
||||
local RECOMMENDED_BACKEND="cpu"
|
||||
local RECOMMENDED_REASON=""
|
||||
local CAN_BUILD_GPU=false
|
||||
|
||||
# Only recommend Vulkan if GPU is compatible
|
||||
if [[ "$HAS_VULKAN" == "yes" && "$HAS_VULKAN_DEV" == "true" && "$VULKAN_COMPATIBLE" == "compatible" ]]; then
|
||||
RECOMMENDED_BACKEND="vulkan"
|
||||
RECOMMENDED_REASON="Vulkan GPU detected with dev libraries"
|
||||
CAN_BUILD_GPU=true
|
||||
elif [[ "$HAS_NVIDIA_GPU" == "yes" && "$HAS_CUDA_DEV" == "true" ]]; then
|
||||
# NVIDIA GPU - best option, uses CUDA
|
||||
if [[ "$HAS_NVIDIA_GPU" == "yes" ]]; then
|
||||
RECOMMENDED_BACKEND="cuda"
|
||||
RECOMMENDED_REASON="NVIDIA GPU with CUDA toolkit"
|
||||
if [[ "$HAS_CUDA_DEV" == "true" ]]; then
|
||||
RECOMMENDED_REASON="NVIDIA GPU with CUDA toolkit installed"
|
||||
else
|
||||
RECOMMENDED_REASON="NVIDIA GPU detected (CUDA toolkit will be installed)"
|
||||
fi
|
||||
CAN_BUILD_GPU=true
|
||||
# Vulkan-compatible GPU (AMD, Intel Gen8+) - second choice
|
||||
elif [[ "$HAS_VULKAN" == "yes" && "$VULKAN_COMPATIBLE" == "compatible" ]]; then
|
||||
RECOMMENDED_BACKEND="vulkan"
|
||||
if [[ "$HAS_VULKAN_DEV" == "true" ]]; then
|
||||
RECOMMENDED_REASON="Vulkan GPU detected with dev libraries"
|
||||
else
|
||||
RECOMMENDED_REASON="Vulkan GPU detected (dev libraries will be installed)"
|
||||
fi
|
||||
CAN_BUILD_GPU=true
|
||||
# Vulkan GPU but compatibility unknown - allow GPU build as fallback
|
||||
elif [[ "$HAS_VULKAN" == "yes" && "$VULKAN_COMPATIBLE" == "unknown" ]]; then
|
||||
RECOMMENDED_BACKEND="vulkan"
|
||||
RECOMMENDED_REASON="Possible Vulkan GPU (will verify during build)"
|
||||
CAN_BUILD_GPU=true
|
||||
# Incompatible Vulkan GPU (old Intel Gen7) - CPU only
|
||||
elif [[ "$VULKAN_COMPATIBLE" == "incompatible" ]]; then
|
||||
RECOMMENDED_BACKEND="cpu"
|
||||
RECOMMENDED_REASON="Incompatible GPU ($VULKAN_COMPAT_REASON) - CPU mode recommended"
|
||||
CAN_BUILD_GPU=false
|
||||
elif [[ "$HAS_VULKAN" == "yes" || "$HAS_NVIDIA_GPU" == "yes" ]]; then
|
||||
RECOMMENDED_BACKEND="cpu"
|
||||
if [[ "$HAS_VULKAN" == "yes" ]]; then
|
||||
RECOMMENDED_REASON="GPU detected but dev libraries missing (will use CPU)"
|
||||
else
|
||||
RECOMMENDED_REASON="NVIDIA GPU detected but CUDA not installed (will use CPU)"
|
||||
fi
|
||||
CAN_BUILD_GPU=false
|
||||
else
|
||||
RECOMMENDED_BACKEND="cpu"
|
||||
RECOMMENDED_REASON="No compatible GPU detected"
|
||||
|
||||
Reference in New Issue
Block a user