Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion bin/omarchy-hw-hybrid-gpu
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,29 @@

# omarchy:summary=Detect whether the system has an active hybrid GPU configuration

# Read the cached sysfs IDs rather than lspci, which reads PCI config space and
# resumes a runtime-suspended GPU. This gate is what the Hybrid GPU menu row is
# guarded by, so asking it used to wake the discrete card the row is about --
# 2.6s on this laptop, and the card then stays powered. omarchy-hw-nvidia
# already reads the same files for the same reason.
#
# Counting by class also stops "Non-VGA unclassified device" being counted as a
# GPU: the old pattern matched the VGA inside Non-VGA, so a machine with one
# graphics card and one such device counted two and called itself hybrid.
pci_devices_path="${OMARCHY_PCI_DEVICES_PATH:-/sys/bus/pci/devices}"

multiple_gpus() {
(($(lspci | grep -cE 'VGA|3D|Display') >= 2))
local device count=0

shopt -s nullglob

for device in "$pci_devices_path"/*; do
[[ -r $device/class ]] || continue
# 0x03 is the PCI display-controller class: VGA, XGA, 3D and other.
[[ $(< "$device/class") == 0x03* ]] && ((count++))
done

((count >= 2))
}

if omarchy-cmd-present supergfxctl; then
Expand Down
49 changes: 41 additions & 8 deletions test/shell.d/hw-hybrid-gpu-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,30 @@ esac
printf '%s\n' "${SUPPORTED_MODES:-Integrated Hybrid}"
STUB

cat >"$fake_bin/lspci" <<'STUB'
#!/bin/bash
chmod +x "$fake_bin"/*

for _ in $(seq "${GPU_COUNT:-1}"); do
echo "0000:00:02.0 VGA compatible controller: Stub GPU"
done
STUB
# The detector counts display controllers out of sysfs rather than parsing
# lspci, so the GPUs are faked as PCI device directories. Every tree also holds
# an unclassified device, which lspci prints as "Non-VGA unclassified device":
# the old pattern matched the VGA inside Non-VGA and counted it as a GPU.
make_pci_tree() {
local count=$1 tree="$test_tmp/pci-$1" i

chmod +x "$fake_bin"/*
rm -rf "$tree"
for ((i = 0; i < count; i++)); do
mkdir -p "$tree/0000:0$i:02.0"
printf '0x030000\n' >"$tree/0000:0$i:02.0/class"
done

mkdir -p "$tree/0000:80:14.5"
printf '0x000000\n' >"$tree/0000:80:14.5/class"

printf '%s' "$tree"
}

hybrid_gpu() {
PATH="$fake_bin:$PATH" timeout --kill-after=1s 10s bash "$ROOT/bin/omarchy-hw-hybrid-gpu"
PATH="$fake_bin:$PATH" OMARCHY_PCI_DEVICES_PATH="$(make_pci_tree "${GPU_COUNT:-1}")" \
timeout --kill-after=1s 10s bash "$ROOT/bin/omarchy-hw-hybrid-gpu"
}

hybrid_gpu ||
Expand Down Expand Up @@ -89,3 +101,24 @@ chmod +x "$fake_bin/omarchy-cmd-present"
GPU_COUNT=2 hybrid_gpu ||
fail "hybrid GPU detection counts GPUs without supergfxctl"
pass "hybrid GPU detection counts GPUs without supergfxctl"

# The unclassified device in every tree above is the regression: one graphics
# card plus one of those used to count as two and report hybrid.
cat >"$fake_bin/omarchy-cmd-present" <<'STUB'
#!/bin/bash
exit 1
STUB
chmod +x "$fake_bin/omarchy-cmd-present"

GPU_COUNT=1 hybrid_gpu
status=$?
((status == 1)) ||
fail "one graphics card beside an unclassified device is not hybrid" "exit status: $status"
pass "an unclassified PCI device is not counted as a graphics card"

# Reading a device's class file does not touch PCI config space, so a suspended
# discrete GPU is not resumed just to answer the menu guard this gate sits in.
# Comments are stripped: the script explains at length why it avoids lspci.
! grep -vE '^[[:space:]]*#' "$ROOT/bin/omarchy-hw-hybrid-gpu" | grep -q 'lspci' ||
fail "the detector must not resume a suspended GPU to count GPUs"
pass "the detector counts GPUs without waking one"