Skip to content

Switch dictation to Vulkan when a GPU is present - #13508

Open
shawnyeager wants to merge 3 commits into
omacom:quattrofrom
shawnyeager:fix/voxtype-enable-vulkan
Open

shawnyeager wants to merge 3 commits into
omacom:quattrofrom
shawnyeager:fix/voxtype-enable-vulkan

Conversation

@shawnyeager

Copy link
Copy Markdown
Contributor

A machine with a Vulkan GPU now gets the Vulkan Voxtype build when dictation is installed. The package's own install links the CPU binary, and the installer called voxtype setup gpu --enable as the user and ignored the failure, so the root-owned link stayed on the CPU build.

On a Dell XPS 14 with an Intel Arc B390, a 2-second clip took 0.90s on that CPU build and 0.19s on Vulkan after the backend was warm.

The package links the CPU binary, and the installer dropped the GPU switch when it could not rewrite that root-owned link.
@llstrk

llstrk commented Sep 29, 2026

Copy link
Copy Markdown

Automated AI review

Community review: Independent automated community review, unaffiliated with the Omarchy team, intended to help prepare PRs for their review.

Outcome: With sudo, the switch now affects Haswell iGPUs and aarch64, where Vulkan dictation fails.

Haswell iGPUs get a crashing Vulkan build

omarchy-hw-vulkan accepts any ICD file, and vulkan-intel installs one for every Intel GPU. On a Haswell iGPU with no other supported GPU, the Vulkan build aborts at model load, restarting every 5 s, while the installer still reports ready (#11370). Impact: new installs there crash-loop instead of staying on CPU. Not reproduced.

Suggested change: Keep Haswell on the CPU build, as #11481 does.

Details

Haswell sequence (source-traced, Voxtype 1.1.0, whisper-rs-sys 0.15.0, Mesa 26.2.3):

install/hardware/vulkan.sh      -> vulkan-intel on any Intel GPU (ships intel_hasvk_icd.json)
omarchy-hw-vulkan               -> true (any *.json in icd.d)
sudo voxtype setup gpu --enable -> succeeds (only checks voxtype-vulkan --version)
voxtype.service model load      -> ggml_vk_get_device: "Unsupported device" (no 16-bit storage)
                                -> uncaught C++ exception across FFI, abort
Restart=on-failure, RestartSec=5 -> crash loop; installer still says "Voxtype Dictation Ready"

aarch64 installs stop halfway

aarch64 voxtype-bin ships no voxtype-vulkan, so with any Vulkan ICD the switch fails and set -e exits before voxtype setup systemd. Impact: Install > Dictation shows as installed, but the service is never set up.

Suggested change: Also require [[ -x /usr/lib/voxtype/voxtype-vulkan ]].

Reproducer (fails at 9e6f383)

Reproducer: aarch64 install stops after the Vulkan switch fails

Stub-based test in the style of test/shell.d/voxtype-install-test.sh. Save it as test/shell.d/voxtype-install-arch-test.sh and run bash test/shell.d/voxtype-install-arch-test.sh. It stubs every command the installer calls (nothing touches the host) and models the two voxtype-bin 1.1.0 package layouts: x86_64 ships /usr/lib/voxtype/voxtype-vulkan; aarch64 ships the voxtype-cpu and voxtype-onnx engine binaries and no voxtype-vulkan. The voxtype stub mirrors enable() in Voxtype 1.1.0 src/setup/gpu.rs, which returns "Vulkan backend not installed" when that binary is missing.

It is a model of the package, not a run on aarch64 hardware.

#!/bin/bash

set -euo pipefail

source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"

test_home=$(mktemp -d)
test_bin=$(mktemp -d)
omarchy_path=$(mktemp -d)
voxtype_lib=$(mktemp -d)
log_file=$(mktemp)

cleanup() {
  rm -rf "$test_home" "$test_bin" "$omarchy_path" "$voxtype_lib"
  rm -f "$log_file"
}
trap cleanup EXIT

mkdir -p "$omarchy_path/default/voxtype"
printf 'engine = "whisper"\n' >"$omarchy_path/default/voxtype/config.toml"

write_stub() {
  local name="$1"
  local body="$2"
  printf '%s\n' '#!/bin/bash' "$body" >"$test_bin/$name"
  chmod +x "$test_bin/$name"
}

write_stub gum '[[ $1 == confirm ]] && exit 0
exit 1'
write_stub omarchy-pkg-add 'exit 0'
write_stub hyprctl 'echo "hyprctl:$*" >>"$TEST_LOG"'
write_stub omarchy-restart-shell 'exit 0'
write_stub omarchy-notification-send 'echo "notify:$*" >>"$TEST_LOG"'
write_stub systemctl 'echo "systemctl:$*" >>"$TEST_LOG"'
# omarchy-hw-vulkan only looks for an ICD JSON, which Mesa's vulkan-* packages
# install on aarch64 too.
write_stub omarchy-hw-vulkan 'exit 0'
write_stub sudo 'echo "sudo:$*" >>"$TEST_LOG"
"$@"'
# Mirrors voxtype 1.1.0 src/setup/gpu.rs enable(): on the Whisper engine it
# bails before touching /usr/bin/voxtype when no voxtype-vulkan binary exists.
write_stub voxtype 'echo "voxtype:$*" >>"$TEST_LOG"
if [[ $* == "setup gpu --enable" && ! -e $VOXTYPE_LIB/voxtype-vulkan ]]; then
  printf "Error: Vulkan backend not installed.\nThe voxtype-vulkan binary was not found in /usr/lib/voxtype\n" >&2
  exit 1
fi
exit 0'

run_install() {
  : >"$log_file"
  local status=0
  HOME="$test_home" \
    OMARCHY_PATH="$omarchy_path" \
    PATH="$test_bin:$PATH" \
    TEST_LOG="$log_file" \
    VOXTYPE_LIB="$voxtype_lib" \
    bash "$ROOT/bin/omarchy-voxtype-install" || status=$?
  echo "--- installer exit $status, calls:"
  cat "$log_file"
  return "$status"
}

# x86_64 voxtype-bin ships a Vulkan build next to the CPU builds.
touch "$voxtype_lib/voxtype-avx2" "$voxtype_lib/voxtype-avx512" "$voxtype_lib/voxtype-vulkan"
run_install || fail "an x86_64 install with a Vulkan driver finishes"
grep -qx 'voxtype:setup systemd' "$log_file" || fail "an x86_64 install sets up the dictation service"
grep -q '^notify:.*Voxtype Dictation Ready' "$log_file" || fail "an x86_64 install reports dictation ready"
pass "an x86_64 install with a Vulkan driver finishes"

# aarch64 voxtype-bin 1.1.0 ships only voxtype-cpu and voxtype-onnx.
rm -f "$voxtype_lib"/*
touch "$voxtype_lib/voxtype-cpu" "$voxtype_lib/voxtype-onnx"
run_install || fail "an aarch64 install with a Vulkan driver finishes on the CPU build"
grep -qx 'voxtype:setup systemd' "$log_file" || fail "an aarch64 install sets up the dictation service"
grep -q '^notify:.*Voxtype Dictation Ready' "$log_file" || fail "an aarch64 install reports dictation ready"
pass "an aarch64 install with a Vulkan driver finishes on the CPU build"

Output at the PR head (9e6f383)

Exit status: 1

--- installer exit 0, calls:
voxtype:setup --download --no-post-install
sudo:voxtype setup gpu --enable
voxtype:setup gpu --enable
voxtype:setup systemd
hyprctl:reload
notify:-g  Voxtype Dictation Ready Hold F9 to dictate (or toggle with Super + Ctrl + X). -t 10000
ok - an x86_64 install with a Vulkan driver finishes
--- installer exit 1, calls:
voxtype:setup --download --no-post-install
sudo:voxtype setup gpu --enable
voxtype:setup gpu --enable
Error: Vulkan backend not installed.
The voxtype-vulkan binary was not found in /usr/lib/voxtype
not ok - an aarch64 install with a Vulkan driver finishes on the CPU build

Output at the merge-base (3faafba), for comparison

Exit status: 0

--- installer exit 0, calls:
voxtype:setup --download --no-post-install
voxtype:setup gpu --enable
voxtype:setup systemd
hyprctl:reload
notify:-g  Voxtype Dictation Ready Hold F9 to dictate (or toggle with Super + Ctrl + X). -t 10000
ok - an x86_64 install with a Vulkan driver finishes
--- installer exit 0, calls:
voxtype:setup --download --no-post-install
voxtype:setup gpu --enable
voxtype:setup systemd
hyprctl:reload
notify:-g  Voxtype Dictation Ready Hold F9 to dictate (or toggle with Super + Ctrl + X). -t 10000
ok - an aarch64 install with a Vulkan driver finishes on the CPU build
Error: Vulkan backend not installed.
The voxtype-vulkan binary was not found in /usr/lib/voxtype

stdout and stderr are shown one after the other (stdout first), as captured.

Details

Related open PRs: #7129 makes the same one-line change and adds a migration for existing installs (it merges cleanly with this PR). #12901 makes the same change but warns and continues on the CPU build when the switch fails. #11481 conflicts on the same block. #7890 and #8316 each add a different test/shell.d/voxtype-install-test.sh.

Verified:

  • voxtype setup gpu --enable rewrites the root-owned /usr/bin/voxtype, so it needs root; under sudo (default environment) it writes nothing in the user's home.
  • On x86_64 with a working Vulkan GPU, voxtype setup systemd runs afterwards, so the daemon starts on the Vulkan build, and package upgrades keep the choice.
  • The new test fails at the merge-base (no sudo line; the failed switch exits 0) and passes at this head.

Optional test improvement: the failure case only checks for a non-zero exit, so any unrelated failure passes it. Asserting the sudo:voxtype setup gpu --enable line and the absence of voxtype:setup systemd would tie it to the switch.

More findings

Re-running the installer overrides a chosen backend

setup gpu --enable follows the active /usr/bin/voxtype, not the config, so a re-run with omarchy voxtype install re-enables Vulkan after a manual sudo voxtype setup gpu --disable (the Haswell workaround in #11370). On an ONNX backend it switches to an ONNX GPU build, or on CPUs without AVX-512 fails with "No compatible ONNX GPU backend found" and stops before voxtype setup systemd. Impact: a deliberate backend choice is undone, or the re-run ends as a failed install; the merge-base left the backend unchanged. Source-traced, not reproduced.

Suggested change: Switch only when readlink -f /usr/bin/voxtype is a voxtype-avx* CPU build, as the #7129 migration does.


Review information

Test scope: Source review and sandboxed stub runs at 9e6f383 and the merge-base; no GPU or aarch64 hardware.

AI process: Opus 5.5 Medium coordination and synthesis, Opus 5.5 Xhigh technical review and final fact check, GPT 6 Sol Xhigh search for related issues, Opus 5.5 Medium editorial check.

Opt out: To stop receiving these reviews, reply to this comment saying so.

Haswell stays on the CPU build, and a reinstall disables Vulkan there.
Enable Vulkan only when voxtype-vulkan exists and the current link is
voxtype-avx2 or voxtype-avx512, so aarch64 and a re-run still reach
systemd and do not undo a chosen backend.
@shawnyeager

Copy link
Copy Markdown
Contributor Author

Addressed in c1ce50b:

Haswell stays on the CPU build. omarchy-hw-intel-haswell-gpu matches the Haswell GT PCI IDs, the installer prints why, and a reinstall runs sudo voxtype setup gpu --disable instead of enabling Vulkan.

sudo voxtype setup gpu --enable runs only when voxtype-vulkan is executable and readlink -f of the voxtype symlink is voxtype-avx2 or voxtype-avx512. A missing binary (the aarch64 voxtype-bin layout) is a skip, not a failed install, so voxtype setup systemd still runs. A re-run leaves voxtype-vulkan, voxtype-baseline, ONNX targets, and a manual gpu --disable result alone.

@jandrusk

jandrusk commented Oct 7, 2026

Copy link
Copy Markdown

Thanks for adding the Haswell guard. One gap: Haswell isn't the only GPU that hasvk can't run Whisper on. In Mesa, hasvk only exposes storageBuffer16BitAccess on gfx8 and newer (.storageBuffer16BitAccess = pdevice->info.ver >= 8 in src/intel/vulkan_hasvk/anv_device.c). That means Ivy Bridge and Bay Trail (gfx7) should hit the same "Unsupported device" abort as #11370. Broadwell is gfx8 and should be fine.

Widening the ID match would cover them (maybe under a name like omarchy-hw-intel-gfx7-gpu):

  case "$(<"$device/device")" in
    0x0[4acd][012][26abe]) exit 0 ;;                       # Haswell
    0x015[2567a] | 0x016[26a] | 0x0f3[0-3]) exit 0 ;;      # Ivy Bridge, Bay Trail
  esac

A small one: the Haswell branch runs sudo voxtype setup gpu --disable on every rerun. That goes against the comment above it saying a rerun leaves a manual choice alone (it would undo an ONNX choice, for example). Doing it only when the link points at voxtype-vulkan would match the comment.

`voxtype setup gpu --disable` relinks voxtype-avx2 or voxtype-avx512, which is exactly what the switch matches, so a re-run does re-enable Vulkan after a manual disable. The comment claimed otherwise.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@omarchybot omarchybot added verified Omarchy Triage has verified that this issue is ready for final review and removed bug Something isn't working labels Oct 7, 2026
@omarchybot

Copy link
Copy Markdown
Collaborator

Thanks, @shawnyeager. The fix works. I tested it on a disposable Omarchy VM with the real voxtype-bin 1.1.0 and a Vulkan driver (lavapipe), stubbing only the confirmation prompt and the desktop reload:

  • On quattro, voxtype setup gpu --enable fails with Permission denied (os error 13) and /usr/bin/voxtype stays on voxtype-avx512. At this head it switches to voxtype-vulkan, voxtype.service runs that binary with no restarts, and a second run leaves it alone. With the fix reverted it fails again.
  • With voxtype-vulkan removed (the aarch64 layout), the install skips the switch and finishes on the CPU build.
  • With a Haswell PCI ID simulated through OMARCHY_PCI_DEVICES_PATH, an install that starts on voxtype-vulkan prints the Haswell notice and goes back to voxtype-avx512.
  • test/shell.d/voxtype-install-test.sh passes 16 of 16 here and fails against the quattro installer. ./test/cli is green with this branch merged into current quattro. On the branch's own older base, one unrelated test (vscode generated theme references current theme file) fails; quattro has since fixed it.

Pushed: 9ffa91d corrects the installer comment. It said a re-run leaves a manual gpu --disable alone, but --disable relinks voxtype-avx2 or voxtype-avx512, which is exactly what the switch matches, so a re-run turns Vulkan back on. Nothing else changed.

On @jandrusk's two points, checked against the voxtype-bin install hook and voxtype 1.1.0's src/setup/gpu.rs:

  • Ivy Bridge and Bay Trail: their CPUs have no AVX2, so the package links voxtype-baseline. This installer never switches from that link, so those machines stay on the CPU build without a wider ID match. I couldn't reach Mesa's source to check the 16-bit storage claim myself.
  • The Haswell branch disabling on every run: on a Haswell CPU no ONNX GPU build can be active, since those need AVX-512. On a CPU link, --disable just picks the same CPU build again, so the repeat does no harm.

Against #12901: both PRs fix the same bug, and #12901 is older. I'd still bring this one to the maintainer: #12901 on its own would enable Vulkan on Haswell too and send those machines into the #11370 crash loop, which this PR prevents. Two differences are the maintainer's call. If sudo voxtype setup gpu --enable fails here, the install stops before voxtype setup systemd; #12901 warns and finishes on the CPU build. And #11481 adds the same omarchy-hw-intel-haswell-gpu plus a migration for existing Haswell installs, which this PR doesn't reach; it conflicts with this PR in the installer.

Classification is unsettled. I classify this as a bug fix. At this head, Codex Medium, asked separately, classified it as an enhancement, so it carries no bug or enhancement label. For the same reason it isn't linked to #7099 and #11110 yet, though it fixes both.

Reviewed by Claude Opus 5.5. The second opinion, Codex Medium, reviewed this head and found no defects. It also picked this PR over #12901 when asked without my answer. Independence isn't guaranteed, since it can read my working notes.

This is waiting on the maintainer: to settle the classification, to choose between this and #12901, and to decide how it lands alongside #11481. CI (Greptile) was still running when I wrote this.

@greptile-apps

greptile-apps Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

[Medium risk] Changes dictation GPU acceleration logic based on hardware detection.

The PR appears safe to merge, with a non-blocking slowdown for Haswell machines that also have a usable discrete GPU.

Findings

  1. P2 Usable discrete GPUs get disabled ▶

Summary

The installer now uses sudo to switch eligible CPU builds to Vulkan. It adds a Haswell detector, checks that the Vulkan binary exists, and adds shell tests.

  • GPU-switch failures now stop installation instead of being ignored.
  • The Haswell fallback also disables GPU dictation on machines with a usable discrete GPU.

Reviews (1) · Last reviewed commit: "Correct which links a voxtype re-install..." · Reviewed by Greptile

Comment on lines +25 to +27
if omarchy-hw-intel-haswell-gpu; then
echo "Using CPU dictation: Intel Haswell Vulkan lacks the required 16-bit storage."
sudo voxtype setup gpu --disable

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Usable discrete GPUs get disabled

If a machine has Haswell integrated graphics and a usable discrete Vulkan GPU, this branch still runs voxtype setup gpu --disable. The helper matches any Haswell display device, so the installer never checks the other GPU. Users get slower CPU dictation, and reinstalling can disable an already working Vulkan setup. Check for a usable GPU before forcing CPU dictation.

@jandrusk

jandrusk commented Oct 8, 2026

Copy link
Copy Markdown

Fair point, thanks for checking. Ivy Bridge and Bay Trail CPUs have no AVX2, so voxtype-bin links voxtype-baseline and this installer never switches them to Vulkan. My gfx7 concern doesn't apply, and the Haswell-only match is enough. Same for the repeat --disable: on a Haswell CPU link, it just re-picks the CPU build. I withdraw both points.

@omarchybot omarchybot removed the verified Omarchy Triage has verified that this issue is ready for final review label Oct 8, 2026
@peteonrails

Copy link
Copy Markdown
Contributor

Thanks for this, @shawnyeager! #14552 moved the installer to bin/omarchy-install-dictation-voxtype, and it still has voxtype setup gpu --enable || true, so this fix is needed as much as ever. That's why it shows conflicts now. Happy to send you the rebased change if that helps, just say the word.

@shawnyeager

Copy link
Copy Markdown
Contributor Author

Thanks for this, @shawnyeager! #14552 moved the installer to bin/omarchy-install-dictation-voxtype, and it still has voxtype setup gpu --enable || true, so this fix is needed as much as ever. That's why it shows conflicts now. Happy to send you the rebased change if that helps, just say the word.

Cheers, @peteonrails. Please do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants