Repository navigation
fix(linux): don't try dma-buf imports on NVIDIA's driver - #2340
Conversation
NVIDIA's driver refuses the guest window's udmabuf dma-bufs as host-visible memory, so every pool fell back to a host-pointer import anyway, and its kernel module logged "NVRM: memMap_IMPL: CPU mapping not supported" at each start. The attempt is no longer made there; other drivers are unchanged. Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Independent check on a second NVIDIA driver (590.48.01)I applied only the
Stock, three starts: every start logged With your hunk, two starts: zero So the diagnosis and the gate hold on a driver you did not test, and the kernel line is gone here too. I did not measure frame times (my runs were short boots), so I can't add to your numbers there. One note: 🤖 Generated with opencode using DeepSeek V4.1 Flash. |
|
Thanks. A second driver was the first thing on my not-tested list, and your run covers it: 590.48.01 refuses the import the same way, and the hunk removes both lines there too. I've added your result to the description. On |
ghost
left a comment
There was a problem hiding this comment.
Looks good. The gate is narrow and in the right place: dev.driver_id is filled in vk_main.cpp before any pool is imported, /dev/udmabuf simply isn't opened on VK_DRIVER_ID_NVIDIA_PROPRIETARY, dmabuf_memfd stays -1, and every pool goes straight to the host-pointer import it already ended up on after each refusal. Other drivers (NVK included, which has its own driver id) take exactly the old path, and the new log reason sits after the existing ones so their messages are unchanged. The fixture covers both routes (no open, no buffer/allocation on the dma route; one host-pointer import on the pool route), and the choice to skip rather than force memory type 0 is well argued with the 2.5 % numbers and the coherency doubt.
@CIB's run on 590.48.01 confirms the same refusal and the same fix on a second driver, so the main "not tested" item is covered. His RX_VK_NO_DMABUF=1 crash is separate from this change (you couldn't reproduce it; an issue with logs would be the place for it).
One nit on consistency with #2111 (inline): the startup warning from reserve_guest in host/hos_main.c runs before the Vulkan device exists, so it can't know the driver and will still tell NVIDIA users without access to ask an admin for /dev/udmabuf, a device the renderer now never uses on NVIDIA. Not worth plumbing the driver into that early probe, but the readme could say NVIDIA users can ignore it.
CI: only the title check has run; the build/test workflows are waiting for a maintainer to approve them (action_required), so they need to go green before merge.
| For fast GPU memory imports on Linux, the game user needs read/write access to `/dev/udmabuf` (the kernel's | ||
| `udmabuf` module). Without it, Hookshot falls back to host-pointer imports, which can be much slower on AMD/RADV; | ||
| `udmabuf` module). Without it, Hookshot falls back to host-pointer imports, which can be much slower on AMD/RADV | ||
| (NVIDIA's driver refuses these dma-bufs, so on NVIDIA the game uses host-pointer imports, which are not slow there); |
There was a problem hiding this comment.
Nit: since #2111 the startup probe in host/hos_main.c still prints the /dev/udmabuf permission denied warning on NVIDIA (it runs before the Vulkan device, so it can't know the driver). Maybe add here that NVIDIA users don't need the access and can ignore that warning, so nobody adds themselves to kvm or writes a udev rule for nothing.
There was a problem hiding this comment.
Done in 6af3759: the paragraph now says that with an NVIDIA card on NVIDIA's own driver you don't need the access and can ignore that warning, and why it still appears (the check runs at the start, before the game knows which GPU it has). I left the early probe itself alone, as you suggest.
The start-up check for /dev/udmabuf (NotRexed#2111) runs before the game knows which GPU it has, so it still warns on NVIDIA's driver, where the renderer no longer opens the device at all. The readme now says that the warning can be ignored there, so nobody joins a device group or writes a udev rule for nothing. (Review of NotRexed#2340.) Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What this is for: a clean start on Linux with NVIDIA's driver. On Linux with NVIDIA's driver, the game asks the driver to import every block of guest memory as a udmabuf dma-buf, the driver refuses every one, and each block ends up a host-pointer import anyway. The attempts leave a kernel line at every start that reads like a driver fault (
NVRM: memMap_IMPL: CPU mapping not supported for addressSpace: 0x1). This change stops asking on NVIDIA's driver. Fixes #2339. What is measured: on one machine (RTX 4090, NVIDIA 615.78.08, Kokiri Forest): the refused imports and the kernel line are gone, and the frame rate is unchanged within the spread of identical runs (80.4 and 81.3 fps before, 79.6 and 81.5 after). Not measured: any other NVIDIA card or driver version, any other area, and whether the refusals ever cost a visible hitch in play. So this is a cleanup of the log and the start, not a speed-up.Problem
/dev/udmabuf(perf(linux): hand guest memory to the GPU as udmabuf dma-bufs, not host pointers #448). The readme gives the reason: host-pointer imports can be much slower on AMD with RADV.import_dma_buf(gpu/vk/vk_memory.cpp) makes a udmabuf anddma_buf_memoryasks the driver which memory types it allows for it. NVIDIA's driver answers with two (allowed bits 0x9): type 0 with no flags, and type 3, host visible, coherent and cached. The code takes the first host-visible and coherent one: type 3.VK_ERROR_OUT_OF_DEVICE_MEMORY(vk: guest ...: its dma-buf not imported (VkResult -2)), for every pool, and a pool made of several pieces stays unbound (its 0 dma-bufs not bound (VkResult -13)).memMap_IMPLline 0.17 to 0.6 ms into it. Later refusals take microseconds and usually print nothing, but 2 of my 18 measured runs ofmainprinted the line three times. One later refusal, of a 64 MB piece during a save's load, took 198 ms on the presentation thread. I saw that once and can't say how often it happens.What changed
gpu/vk/vk_memory.cpp,import_dma_buf:/dev/udmabufis not opened whendev.driver_idisVK_DRIVER_ID_NVIDIA_PROPRIETARY, so no dma-buf is made or offered and every pool takes the host-pointer import from the start, as it already did after each refusal. The start-up line says why:vk: guest memory as dma-bufs: no (NVIDIA's driver refuses them: host pointers). Other drivers take the same path as before: the driver check is the only new condition.readme.md: the udmabuf paragraph says that NVIDIA's driver refuses these dma-bufs and the game uses host-pointer imports there.tests/import_buffer_binding_test.cpp: the fixture's device gets adriver_id, itsopencounts calls, and a newnvidiacase checks the dma route (noopen, no buffer, no allocation, no memfd kept) and the pool route (one host-pointer import).tests/test_import_buffer_binding.py: runs the new case on both routes (37 cases, was 34).Why skip the attempt instead of picking the other memory type. The driver does accept type 0: with an experiment that forced it, all 60 imports of a run succeeded and no kernel line appeared. But Kokiri Forest ran 2.5 % slower that way (79.17 and 78.53 fps against 80.63 and 81.13 with host pointers, taken in turn; identical runs differed by 0.6 to 0.8 %). I also don't know whether the GPU sees the CPU's writes coherently through an import that isn't host visible. So host pointers stay.
How it was tested
Environment: RTX 4090, NVIDIA 615.78.08 with its open kernel module, i9-13900K, 96 GB, Arch Linux (kernel 7.2.15), headless (
HOS_HEADLESS=1, no window), a build from source with clang 23.The test.
tests/test_import_buffer_binding.pypasses with the change (g++ and clang++). The new fixture againstmain'svk_memory.cppfails:fixture-0.exe dma nvidiaaborts on its assert.All checks.
python -I -B tests/run_all.pyon the branch: 361 passed, 3 failed, 10 skipped. The three failures are this machine's and don't touch the change:tests/test_updater_asset_digest.pyneeds the .NET 8 SDK (only .NET 10 is here),tests/test_wayland_libdecor_hint.pytrips a clang 23 warning under-Werror, andnx2/test_unsigned_image_types.pyfailed to compile while the load average was 120 to 370 and passes when run alone. That run was on the commit before a last edit that changed only a code comment; after the edit I rerantest_import_buffer_binding.pyalone (passes).In the game.
mainbdfe09c with this commit against bdfe09c, the two renderers built the same way. The user's save in Kokiri Forest, 13 camera turns of 4 s, uncapped (HOS_FPS_MAX=240), output 2048x1152, Render resolution Auto, no frame generation. Four runs of 90 s in turn (base, fix, base, fix) with nothing else on the card and no build running. The frame times are the game's own present-to-present intervals (HOS_PRESENT_TRACE) over the 30 s from 15 s after the save's load.The log and the kernel, per run:
("refused imports 7" is what the log shows before its own limit of 8 such lines; the count with a line per attempt is the 49 to 50 above.)
The frames, per run:
Added 2026-11-11 15:56 UTC: a second driver, run by @CIB (his comment below). RTX 4090, NVIDIA 590.48.01 (open kernel module), Arch Linux, kernel 6.19.8; only the
vk_memory.cpphunk, on main 8c92fe3 in a tree with unrelated local scheduler work. Stock, three starts: each logs the refused imports (7 lines on a first start, 1 on the next two) and adds onememMap_IMPLline to the kernel log. With the hunk, two starts: neither line, and the newvk: guest memory as dma-bufs: no (NVIDIA's driver refuses them: host pointers). Frame times were not measured there.Risks
VK_DRIVER_ID_NVIDIA_PROPRIETARYmatched here with the open kernel module. Mesa's NVK reports a different driver id and keeps trying dma-bufs as before; I have not run it.RX_VK_NO_DMABUF=1andHOS_GUEST_MEMFD=0work as before.Not tested
Other NVIDIA cards, driver versions other than 615.78.08 (mine) and 590.48.01 (CIB's short starts), NVIDIA's closed kernel module, NVK, AMD, Intel, a run with a window, areas other than Kokiri Forest, the Steam Deck. Windows doesn't reach this code.
Other open pull requests
Twelve open pull requests touch
gpu/vk/vk_memory.cpp. None changes these lines. #2042 changes the line two above (getenv("RX_VK_NO_DMABUF")toenv_on(...)) and the same two test files; git merges the two without a conflict, and the merged function has both changes.Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com