From 416fa4876018e5fbb9c3f537ea9c353d1d8b9982 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Sun, 4 Oct 2026 18:52:40 +0200 Subject: feat(gpu): show VRAM in use as a bar with a percentage Sum drm-resident-vram0 from DRM fdinfo, the same per-client counters gputop reads, counting each drm-client-id once since a client repeats its totals on every fd it holds. One grep over /proc/*/fdinfo, about 10ms warm, sampled through new_gate every ~2s. The 12 GiB total is hardcoded: xe exposes no VRAM capacity in sysfs. Co-Authored-By: Claude Opus 5.5 --- lib/data.lua | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'lib/data.lua') diff --git a/lib/data.lua b/lib/data.lua index 7ae96a7..d02d0f7 100644 --- a/lib/data.lua +++ b/lib/data.lua @@ -690,4 +690,45 @@ function M.nvtable_parse(text) return seen and out or nil end +-- VRAM in use on an xe device, in bytes, from DRM fdinfo: the same source +-- gputop reads. Input is `grep -H` output, one 'path:key:value' line per +-- field, so fields are grouped by the fd file they came from. +-- +-- One client (drm-client-id) is usually open on several fds, each repeating +-- the client's full totals, so clients are counted once, not fds. Buffers +-- shared between clients are still counted in each, as gputop does. +local UNIT = { B = 1, KiB = 1024, MiB = 1024 ^ 2, GiB = 1024 ^ 3 } + +function M.drm_vram_parse(text) + if type(text) ~= 'string' then return nil end + local fds = {} + for path, key, val in text:gmatch('([^\n]-):(drm%-[%w%-]+):%s*([^\n]*)') do + local fd = fds[path] or {} + fds[path] = fd + fd[key] = val + end + local seen, total = {}, nil + for _, fd in pairs(fds) do + local id = fd['drm-client-id'] + local n, unit = (fd['drm-resident-vram0'] or ''):match('^(%d+)%s*(%a*)') + if fd['drm-driver'] == 'xe' and id and n and not seen[id] then + seen[id] = true + total = (total or 0) + tonumber(n) * (UNIT[unit ~= '' and unit or 'B'] or 1) + end + end + return total +end + +-- ponytail: a popen per call, ~10ms warm; callers gate it. Only fds of +-- processes readable by conky's user are seen, so another user's GPU client +-- (a system service) is not counted. +function M.drm_vram() + local p = io.popen("grep -sH -e '^drm-driver' -e '^drm-client-id'" + .. " -e '^drm-resident-vram0' /proc/[0-9]*/fdinfo/* 2>/dev/null") + if not p then return nil end + local out = p:read('*a') + p:close() + return M.drm_vram_parse(out) +end + return M -- cgit v1.2.3