Skip to content

Native Windows Intel GPU detection - #17

Draft
offbyonebit wants to merge 1 commit into
mainfrom
windows-gpu-detect
Draft

Native Windows Intel GPU detection#17
offbyonebit wants to merge 1 commit into
mainfrom
windows-gpu-detect

Conversation

@offbyonebit

Copy link
Copy Markdown
Owner

Why

detect_gpus() walked /sys/bus/pci/devices, so on Windows it returned [] and arc-llama init exited with "Windows auto-detection is not supported yet". #11 made paths, the launcher and the CLI Windows-safe but never touched hardware discovery, so a Windows user could pip install arc-llama and then had nowhere to go.

The Intel Arc community skews heavily Windows, so the people most likely to adopt this currently cannot run it.

What

detect_gpus() now dispatches by platform. The Windows path:

  • enumerates Intel display adapters from the registry
  • reads bus/device/function from cfgmgr32 numeric device-node properties
  • takes VRAM from HardwareInformation.qwMemorySize, falling back to the existing device-ID table
  • parses device IDs out of PNP instance strings so arch_for_device_id() works unchanged

Linux detection is untouched.

Design notes

pci_slot is synthesised as the same 0000:bb:dd.f string Linux produces, not an enumeration index. It is a config key that has to survive reboots, and this keeps configs portable across platforms.

Location comes from numeric properties, not the LocationInformation string. That string is written by the PCI bus driver and can be localized, so an English-only parse would silently find zero GPUs on a German or Japanese install. It is kept only as a last-resort fallback, and notes when used.

No COM. VRAM is deliberately not read via DXGI. Hand-rolled COM vtable dispatch through ctypes turns a wrong offset into an access violation that no try/except can catch, which would break this module's rule that detection degrades rather than raises.

Known weak spot: sycl_index

Level Zero enumeration order on Windows is not documented to follow PCI order. It is probed from sycl-ls when present, otherwise guessed from PCI order with a note telling the user to override. For two identical cards this is the thing most likely to be wrong, and a wrong mapping silently sends work to the wrong GPU.

Needs confirmation on real hardware

Neither maintainer machine nor CI has an Intel GPU on Windows, so these are unverified:

  • CM_DRP_ADDRESS packs device in the high 16 bits and function in the low 16. Confirm the synthesised slot matches the physical slot in Device Manager / GPU-Z (detect.py:157)
  • The {hw_id}\{inst_id} device-instance ID format is what CM_Locate_DevNodeW expects (detect.py:282)
  • sycl-ls bracket format across oneAPI versions (detect.py:502)
  • Two identical Arc cards: does the assigned sycl_index actually match the Level Zero ordinal? See Test multi-GPU swap policy on a 2+ Arc system #2
  • A discrete Arc alongside an Intel iGPU picks the discrete card
  • A non-English Windows install still detects correctly via the numeric path

Testing

Fixture-driven with the Windows calls monkeypatched, so they run on Linux and on windows-latest, neither of which has an Intel GPU. 24 detect tests pass, ruff clean.

Draft until someone with a Windows Arc box confirms the checklist above.

🤖 Generated with Claude Code

detect_gpus() previously walked /sys/bus/pci/devices, so on Windows it
returned an empty list and `arc-llama init` dead-ended with "Windows
auto-detection is not supported yet". PR #11 made paths, the launcher and
the CLI Windows-safe but never touched hardware discovery, so Windows
users could install the package and then had nowhere to go.

detect_gpus() now dispatches by platform. The Windows path enumerates
Intel display adapters from the registry, reads bus/device/function from
cfgmgr32 numeric device-node properties, and takes VRAM from the
display-class HardwareInformation.qwMemorySize value, falling back to the
existing device-ID table. Device IDs are parsed out of PNP instance
strings so the arch_for_device_id() table keeps working unchanged.

Two deliberate choices worth calling out:

pci_slot is a config key that has to survive reboots, so it is synthesised
as the same 0000:bb:dd.f string the Linux path produces rather than any
enumeration index. Configs stay readable and portable across platforms.

Bus/device/function come from the numeric cfgmgr32 properties, not from
parsing the LocationInformation string. That string is written by the PCI
bus driver and can be localized, so an English-only parse would silently
find zero GPUs on a German or Japanese install. The string parse is kept
only as a last-resort fallback and notes when it is used.

No COM: VRAM is not read through DXGI. Hand-rolled COM vtable dispatch via
ctypes turns a wrong offset into an access violation that no try/except
can catch, which would break this module's rule that detection degrades
rather than raises.

sycl_index remains best-effort. Level Zero enumeration order on Windows is
not documented to follow PCI order, so it is probed from sycl-ls when
available and otherwise guessed from PCI order with a note telling the
user to override. This is the known-weak spot for multiple identical
cards and needs hardware confirmation.

Tests are fixture-driven with the Windows calls monkeypatched so they run
on Linux and on GitHub's windows-latest runners, neither of which has an
Intel GPU. Linux detection is unchanged and still covered.
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.

1 participant