Repository navigation
Conversation
|
About holding buffers in (And I'm really sorry for whatever copilot thing is??? It never happened in my other PRs, I have no idea why it was even enabled) |
I don't think anyone's explicitly enabled anything Copilot related on this repo. Maybe something Github has turned on by default that we may want to disable... |
|
So the idea of Something I was wondering is if we can just allocate a udmabuf file descriptor for the whole Does that amount to the same thing as creating multiple udmabufs with different offsets? And perform the same? If so we may need to create new udmabufs on pool resizes, but it sounds cleaner than trying to make assumptions about how many buffers to cache per pool. |
|
Yeah that's it, every I've considered one udmabuf per pool. For the gpu it's the same thing and works fine, but it's not faster, the renderer caches imports per Dmabuf, so a new Dmabuf per wl_buffer means a new import every frame, increasing cpu usage, and +- doubling import time. Fixing that needs the same cache again. About buffers number: my description was a bit misleading, it's up to 4, not always 4. Cache only keeps layouts pool actually used, and the vast majority of apps use only one. Dynamic number is easy to implement I think, but I don't know any app using more than 4, and if it needs more it will just create a new udmabuf, which is still faster than copying |
Just passing by, and also not sure if it will have any impact at all, but it seems udmabuf's 64MiB limit has been lifted in Linux 7.3 (original series https://lists.freedesktop.org/archives/dri-devel/2026-July/583848.html). |
Drakulix
left a comment
There was a problem hiding this comment.
Thanks for taking a stab at this, in general this looks really good.
I wish we could just unconditionally import all shm bufs as udmabufs and not make this renderer-specific, but given the current constraints, this seems like a really solid implementation.
Just a couple of remarks, since I would want to allow downstream to be able to control some aspects of this more precisely.
| /// Client buffers the GPU reads directly while rendering this frame (shm via udmabuf). | ||
| /// Keeping them alive delays their `wl_buffer.release` until the frame is showed, | ||
| /// when GPU is done reading them. | ||
| sampled_buffers: Vec<crate::backend::renderer::utils::Buffer>, |
There was a problem hiding this comment.
I am a little unsure why this is necessary. I thought we already hold the buffer in the DrmScanoutBuffer as part of the plane state?
Ping @cmeissl
There was a problem hiding this comment.
Plane state only holds a client buffer when it's put directly on a plane. Udmabuf shm buffers get rendered into the swapchain buffer instead so nothing keeps them. My comment was a bit misleading, fixed it
Also they only need to live until the frame is presented, in plane state they'd live one frame longer, which isn't a big deal, but clients with 2 buffers would get theirs back up to a frame later
There was a problem hiding this comment.
But that would affect normal dmabuf buffers as well, right? I wonder if the renderer should rather hold buffers until rendering is done, that seems like the part of the code that should be responsible to me.
There was a problem hiding this comment.
Implicitly synced dmabufs are fine, since the client's gpu write waits for the compositor's read fence. Tho looks like explicit sync have the same problem, release point is signaled when the buffer is dropped, not when the gpu is done. Probably rare, but worth fixing
I guess yeah, it's cleaner to implement overall buffer holding in renderer. But I'm not sure where to move it. As a new method on Frame, or OutputDamageTracker if possible, which already has the drawn elements and the SyncPoint from finish(). The latter is better I suppose?
There was a problem hiding this comment.
Ideally a GlesTexture would hold a weak reference, which is upgraded and stored on render_texture.
Given this also concerns explicit sync: ping @ids1024
Only integrated GPUs are allowed. Discrete would read udmabuf over PCIe on every draw, so copying into their own memory is faster if a buffer is drawn more than once. Known broken ones: - nvidia-drm: sometimes shows outdated data, `DMA_BUF_IOCTL_SYNC` doesn't help - i915 without LLC: CPU cache is flushed only on the first import - virtio_gpu: breaks virgl context (KWin report, precaution) - vmwgfx: kernel leak (KWin report, precaution)
gpu reads use DMA_BUF_IOCTL_SYNC for sync, END on every import, and START right after udmabuf creation (since the kernel rejects END without a preceding START). The syncs only matter where CPU caches aren't coherent with the GPU (e.g. many ARM SoCs).
Delays their wl_buffer.release until gpu is done reading them, so `wait_udmabuf_idle` doesn't block the compositor for miliseconds. Unlike `wait_udmabuf_idle`, this also works on gpus that don't report their reads (e.g. nvidia).

Description
Import shm buffers via udmabuf.
Closes #2044, indirectly helps a bit with #1652.
Details
prefers_udmabuf, but it's a breaking change.wl_buffer.releasewhile the gpu is still reading it. Two solutions are implemented: a blocking one via a fence, and a fast non blocking one via DrmCompositor (not a driver workaround). Fence is still required when DrmCompositor isn't available.create_buffer_from_memfd:removed the stride and offset checks. Offset and size no longer need to be page multiples: the udmabuf starts at the page boundary, and the remainder is passed as the plane offset.Testing results
Intel Tiger Lake + NVIDIA GeForce RTX 3050 Ti Mobile, using Cosmic and anvil.
Results on Intel:
wl_buffer.releasegoes from 1.6 ms to 19 microseconds with itsmall note: Nvidia stale pixel issue (the reason it's fully denied in kde) occurs very rarely for me, but it was widely reported in Kde, so there's no point in making an exception for Nvidia.
Checklist