Skip to content

Add Intel Xe GPU driver support - #1457

Open
deveworld wants to merge 1 commit into
aristocratos:mainfrom
deveworld:feature/xe-gpu-support
Open

deveworld wants to merge 1 commit into
aristocratos:mainfrom
deveworld:feature/xe-gpu-support

Conversation

@deveworld

@deveworld deveworld commented Jan 10, 2026 •

Copy link
Copy Markdown

Summary

Adds support for Intel GPUs on the Xe kernel driver (Lunar Lake, Battlemage, newer Arc / Arc Pro), which the i915 path can't detect.

Closes #1407

What Changed

  • Xe collection path in src/linux/btop_collect.cpp, with multi-GPU discovery and per-device i915/xe routing
  • src/linux/xe_drm.h with the Xe UAPI definitions needed for the VRAM query
  • RC/MC split graphs for Xe
  • src/linux/intel_gpu_top/ is unchanged

Metrics (Xe)

Metric Source
Utilization fdinfo drm-cycles-*; gtidle sysfs when no client is visible
Clock tile0/gt*/freq0/cur_freq
VRAM DRM_XE_DEVICE_QUERY_MEM_REGIONS, dedicated VRAM only
Power hwmon energy1_input (card) or energy2_input (package), discrete cards only
Temperature not implemented

Utilization per engine class is Δcycles / (Δtotal × drm-engine-capacity), and the GPU total is the busiest class, like intel_gpu_top. Counters are kept per drm-client-id, so a client exiting doesn't affect the others. No smoothing.

No root needed. Without access to the render node, VRAM is skipped and the rest still works. SR-IOV VFs have no gtidle, so they show VRAM only.

Performance

The fdinfo scan runs at most every 500 ms on the collector thread: ~25–40 ms per scan on Lunar Lake (Core Ultra 5 228V). Logged at --debug as Xe: fdinfo scan <ms>.

Known limitations

  • fdinfo only covers processes btop can read, so unprivileged runs miss other users' clients
  • Integrated GPUs have no xe hwmon, so there is no power reading
  • Devices missing from the bundled name table show as "Intel GPU"

Testing

  • make, CMake + ctest, CMake with -DBTOP_GPU=OFF
  • Lunar Lake: render (vkcube) and AV1 encode load, compared against raw fdinfo and nvtop
  • Power and multi-engine capacity need a discrete card, so they're untested locally

Copilot AI review requested due to automatic review settings January 10, 2026 12:29
@deveworld
deveworld force-pushed the feature/xe-gpu-support branch from e5e3853 to 1f8f375 Compare January 10, 2026 12:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds support for Intel GPUs using the Xe kernel driver, which is required for newer Intel hardware like Lunar Lake and Battlemage that don't use the legacy i915 driver.

Changes:

  • Added minimal xe_drm.h header with UAPI definitions for interfacing with the Xe driver
  • Implemented Xe namespace with PMU-based GPU monitoring using perf events
  • Added dynamic driver detection and PMU device discovery to support both i915 and Xe drivers
  • Routes collection to appropriate code path based on detected driver type

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 14 comments.

File Description
src/linux/xe_drm.h New header file containing minimal Xe DRM UAPI definitions (structs and ioctls) for device query and engine enumeration
src/linux/btop_collect.cpp Added Xe namespace with PMU-based monitoring, dynamic driver detection, PMU device discovery, and routing logic to switch between i915 and Xe code paths
Comments suppressed due to low confidence (1)

src/linux/btop_collect.cpp:2103

  • Missing free() call for gpu_path on error path. If get_intel_device_id() returns null, the function returns false without freeing gpu_path that was allocated by find_intel_gpu_dir().
			char *gpu_device_id = get_intel_device_id(gpu_path);
			if (!gpu_device_id) {
				Logger::debug("Failed to find Intel GPU device ID, Intel GPUs will not be detected");
				return false;

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/linux/btop_collect.cpp Outdated
Comment thread src/linux/btop_collect.cpp Outdated
Comment thread src/linux/btop_collect.cpp Outdated
Comment thread src/linux/btop_collect.cpp Outdated
Comment thread src/linux/btop_collect.cpp Outdated
Comment thread src/linux/btop_collect.cpp Outdated
Comment thread src/linux/btop_collect.cpp Outdated
Comment thread src/linux/btop_collect.cpp Outdated
Comment thread src/linux/btop_collect.cpp Outdated
Comment thread src/linux/btop_collect.cpp Outdated
@aristocratos aristocratos added the AI generated Majority of included code is AI generated label Jan 15, 2026
@aristocratos aristocratos changed the title [AI generated] Add Intel Xe GPU driver support Add Intel Xe GPU driver support Jan 15, 2026
@deckstose deckstose added the gpu Issues or pull requests related to GPU functionality label Jan 25, 2026
@deveworld
deveworld force-pushed the feature/xe-gpu-support branch from 178426b to c4341c0 Compare January 30, 2026 17:58
@TheSovietPancakes

Copy link
Copy Markdown
Contributor

@deveworld
deveworld force-pushed the feature/xe-gpu-support branch from 1b841c3 to cc2af96 Compare February 1, 2026 17:02
@deveworld

Copy link
Copy Markdown
Author

Please do not reformat code if you can

Thanks for the feedback!
I've restored fmt::format usage and the clang diagnostic pragma.
It should now match the original code style

@TheSovietPancakes

Copy link
Copy Markdown
Contributor

I was referring to the code style. Please continue using fmt, since this is preferred. But I was referring to things like changing the indentation of completely unrelated code. This makes for a larger diff and can sometimes get your PR rejected outright in some repositories.
(@deckstose Ngl this would be a really great usecase for .clang-format, it's starting to warm up on me 😆)
If you can make one big change to fix Intel, without touching other code, that would be awesome 😄

@deveworld
deveworld force-pushed the feature/xe-gpu-support branch from cc2af96 to 45aa98f Compare February 2, 2026 15:47
@MrChuw

MrChuw commented Feb 25, 2026

Copy link
Copy Markdown

I tested on my B580 sparkle, it works as expected, but I have a suggestion, how about using nvtop if available, the nvtop -i (or -i) option provides an output in json format with memory and power usage and also temperature and more.

2026-02-25_13-23-28-423

Here a example of nvtop output.

[
  {
   "device_name": "Battlemage G21 (Arc B580)",
   "gpu_clock": "1200MHz",
   "mem_clock": null,
   "temp": "54C",
   "fan_speed": "0RPM",
   "power_draw": "43W",
   "gpu_util": "11%",
   "encode_decode": "0%",
   "mem_util": "54%",
   "mem_total": "12809404416",
   "mem_used": "6956257280",
   "mem_free": "5853147136",
   "processes" : [
     {
       "pid": "1",
       "cmdline": "/usr/lib/systemd/systemd --switched-root --system --deserialize=56",
       "kind": "graphic",
       "user": "root",
       "gpu_usage": "0%",
       "gpu_mem_bytes_alloc": null,
       "gpu_mem_usage": null,
       "encode_decode": "0%"
     },
     {
       "pid": "894",
       "cmdline": "/usr/lib/systemd/systemd-logind",
       "kind": "graphic",
       "user": "root",
       "gpu_usage": "0%",
       "gpu_mem_bytes_alloc": null,
       "gpu_mem_usage": null,
       "encode_decode": "0%"
     }
   ]
  }
]

@PrakarshPanwar

Copy link
Copy Markdown

Works well on my both laptops, Tiger Lake-H and Raptor Lake-P iGPUs. No need for sudo access to read GPU stats. When it will be merged?

@deveworld

Copy link
Copy Markdown
Author

Rebased this on current upstream/main, cleaned up the Xe path, and updated the PR description so it matches the code again.

The branch now prefers fdinfo for utilization, keeps gtidle/PMU as fallback, handles drm-engine-capacity-* when available, and only reports actual dedicated VRAM. I also fixed the remaining local Xe build warnings.

I reran make -j4 and cmake -S . -B build-test && cmake --build build-test -j4 && ctest --test-dir build-test --output-on-failure.

The main limitation still left is that unprivileged fdinfo collection can undercount protected clients.

@MrChuw

MrChuw commented Mar 21, 2026

Copy link
Copy Markdown
2026-03-21_14-49-14-492

latest commit, making the percentage wrong.

@deveworld

Copy link
Copy Markdown
Author

Thanks, @MrChuw

The last Xe fdinfo change was skewing the percentage. I had added drm-engine-capacity-* into the calculation, and that made the reported value too low for cases like the one in your screenshot.

That part is removed, so the latest head should be back to the expected raw fdinfo-style value.

If you get a chance, please try the latest commit again and let me know how it looks.

@MrChuw

MrChuw commented Mar 21, 2026

Copy link
Copy Markdown

The last commit where the GPU utilization on my B580 was right was 45aa98f

the latest commit still with skewed utilization 922a37e

Comment thread src/linux/btop_collect.cpp Outdated
Comment on lines +2029 to +2032
// Collect GPU cycles from all processes' fdinfo with client-id deduplication.
// Keep raw per-class totals so the resulting utilization matches the semantics
// used by existing DRM tools such as nvtop.
static FdinfoCycles collect_fdinfo_cycles(const string& pci_slot) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Whats the performance impact of this? (How long does the collection cycle for GPU take when running btop with --debug when using the fdinfo method?)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

about 24-48 ms per scan on Lunar Lake, throttled to once per 500 ms on the collector thread
Added a --debug line (Xe: fdinfo scan ) to measure it on any device

@deveworld

deveworld commented Apr 17, 2026 •

Copy link
Copy Markdown
Author

Rebased and pushed.

@aristocratos, collect_fdinfo_cycles: 110–150 ms -> ~90 ms/sample after 229e6f6 (/proc/*/fd prefilter). FDINFO_SAMPLE_MIN_NS = 500 ms caps calls. Lunar Lake 228V, ~5000 open fds / ~90 drm fds.

@MrChuw, B580 % restored via 8ad127e (per-class max() on drm-total-cycles instead of sum). Other commits fix late-fdinfo RC/MC activation (f1ecf86), gtidle false-100% on short ticks (d244373), plus dead-code / whitespace / style cleanup.

Deferred to a follow-up PR: multi-engine class capacity normalization (Battlemage VCS=2 / DG2 CCS=4 partial-use underreport).

@deveworld
deveworld force-pushed the feature/xe-gpu-support branch from 0785ff3 to 76530c8 Compare June 24, 2026 03:18
@deveworld

Copy link
Copy Markdown
Author

Force-pushed, rebased onto current main (resolves the merge conflict), squashed to one commit, and integrated with the new AMD Asysfs backend.

New since last review:

  • No root / render group needed. The DRM fd is now optional; if it can't be opened, VRAM is skipped but gtidle/fdinfo utilization and clock still work, so the GPU is shown instead of dropped.
  • Power for discrete Arc via hwmon. Integrated GPUs expose no GPU power sensor (no hwmon, no PMU energy event), so iGPU power isn't available.
  • fdinfo perf: about 24-48 ms/scan on Lunar Lake, throttled to 500 ms; the /proc scan no longer throws on unreadable processes; per-scan time logged at --debug.

Deferred: CCS / multi-engine capacity normalization; i915 still needs PMU permissions.

@temidaradev

Copy link
Copy Markdown

looks accurate so far
image

@jlfranklin

Copy link
Copy Markdown

Looks good on a Debian/forky system:

CPU: 16-core Intel Core Ultra 7 356H (-MCP-)
speed/min/max: 400/400/4700:3700:3300 MHz Kernel: 7.1.8+deb14.1-amd64 x86_64
Up: 3d 17h 18m Mem: 9.15/15.03 GiB (60.9%) Storage: 476.94 GiB (16.7% used)
Procs: 703 Shell: Bash inxi: 3.3.41
image

@stolk

stolk commented Aug 29, 2026

Copy link
Copy Markdown

Works.

The usage seems to have a low pass filter on it, though? I hammer it going from 0 to 100 in a fraction of a second, but:

image_2026-08-29_150559434

@Boladi888

Copy link
Copy Markdown

I've got a little different problem on my asrock B70 pro 32gb

On my system, btop can see the GPU and utilization, but wattage shows as 0.00W. The sensor itself is not dead though. It looks like power is available, just not in the form the current Xe path is expecting.

System:
0000:03:00.0 VGA compatible controller [0300]: Intel Corporation Battlemage G31 [Intel Graphics] [8086:e223]
kernel: 7.0.0-31-generic
btop: 1.4.6, GPU_SUPPORT=true

The relevant hwmon node looks like this:
/sys/class/hwmon/hwmon7/name: xe
/sys/class/hwmon/hwmon7/energy1_label: card
/sys/class/hwmon/hwmon7/energy1_input:
/sys/class/hwmon/hwmon7/energy2_label: pkg
/sys/class/hwmon/hwmon7/power1_label: card
/sys/class/hwmon/hwmon7/power1_cap: 275000000
/sys/class/hwmon/hwmon7/power1_input: missing
/sys/class/hwmon/hwmon7/power1_average: missing

Sampling energy1_input manually gives a real nonzero value. In one sample I got:
Battlemage card energy delta: 414 J over 2.01 s => 206.33 W

So the practical issue is not that Battlemage has no power data. It is that this card exposes cumulative energy for card, and the current path appears to look only for instantaneous power1_average or power1_input.

Would it make sense for the Xe backend to fall back to deriving watts from energy*_input where energy*_label == card when power1_average and power1_input are absent? Basically sample energy twice, divide by elapsed time, and treat that as the same source of truth. Power is not missing here. It is just wearing the wrong sysfs hat.

For images: include one cropped screenshot of btop showing GPU ... 0.00W, but don’t use the full screenshot unless you’re fine with the visible process list and local IP. I’d also include a terminal screenshot or pasted text showing the hwmon7 files and the manual 206 W energy-delta calculation. That second one is the stronger evidence.

image

@BBaoVanC

Copy link
Copy Markdown

I just now tested it on Arch Linux with my Intel Core Ultra 325 iGPU, and I don't see VRAM or power usage. On my desktop with an Arc B580, I see VRAM usage fine but it still doesn't show power. nvtop is able to see VRAM on both devices, and power on the B580 (still not on the Panther Lake iGPU, but that might not be btop's fault)

oursland

This comment was marked as spam.

Add a dedicated Xe collection path for Intel GPUs using the xe kernel
driver (Lunar Lake, Battlemage, newer Arc Pro), which the legacy i915
path cannot detect.

- Add namespace Gpu::Xe in src/linux/btop_collect.cpp with multi-GPU
  discovery and per-instance i915/xe routing
- Add minimal src/linux/xe_drm.h with the Xe UAPI definitions btop needs
- Utilization from fdinfo (drm-cycles-* / drm-total-cycles-*) with
  gtidle sysfs and Xe PMU perf-event fallbacks
- GPU clock from Xe sysfs frequency nodes
- Dedicated VRAM usage via DRM_IOCTL_XE_DEVICE_QUERY (skips SYSMEM-only
  devices so shared system memory is not reported as VRAM)
- GPU power for discrete Arc via hwmon (power1_average/_input); integrated
  GPUs expose no GPU power sensor and report power as unsupported
- Expose RC/MC split graphs (gpu-rc-totals / gpu-mc-totals,
  gt_utilization) without modifying src/linux/intel_gpu_top/
- Keep showing the GPU when the DRM render node can't be opened (e.g. the
  user is not in the 'render' group): VRAM is skipped but gtidle/fdinfo
  utilization and sysfs clock still work, instead of dropping the GPU
- Scan /proc fdinfo without throwing on unreadable (other-user) processes
  and log per-scan duration at --debug level

Does not touch the IGT-imported files, per maintainer feedback on aristocratos#1408.

Squashed from 22 commits and rebased onto upstream/main; integrated with
the new AMD APU/iGPU sysfs backend (Gpu::Asysfs) by offsetting Intel GPU
slots past Asysfs::device_count.

Closes aristocratos#1407
@deveworld
deveworld force-pushed the feature/xe-gpu-support branch from 76530c8 to ca52fdd Compare October 25, 2026 15:36
@deveworld

Copy link
Copy Markdown
Author

Rebased onto main.

  • Utilization per engine class, normalized by drm-engine-capacity-* and tracked per drm-client-id. No smoothing.
  • Power from hwmon energy1_input / energy2_input, which should fix the 0.00W on B70/B580.
  • Removed the PMU fallback, which could never run.
  • Fixed the panel height index.

A B580/B70 power report would help.

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

Labels

AI generated Majority of included code is AI generated gpu Issues or pull requests related to GPU functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Add Intel Xe driver support (Lunar Lake, etc.)