atagen

monolith

public
Star0
Watch0

Commit cacda79c0faa

tarball

atagen <boss@atagen.co>2026-10-19 06:11 UTC

4 files changed+40-2
render-vk: give idle staging memory back

Pooled staging buffers lived until renderer drop and the pool held up to 96 MB, all host-visible and so resident. Under the default 64 MB host blocks gpu-allocator also kept an idle block per memory type. Buffers now expire after two seconds unused, with reaping driven from after_dispatch so an idle compositor still releases them, and 4 MB host blocks give large uploads their own block that is freed with them.
Modified file: crates/monolith/src/state.rs+2 additions
@@ -6,6 +6,7 @@ use crate::wm::{Kind, Wm, configure};
66 use monolith_config::Config;
77 use monolith_layout::{Layout, OutputId, Rect, WindowId};
88 use monolith_render_vk::VulkanRenderer;
9+use smithay::backend::renderer::Renderer;
910 use smithay::desktop::utils::under_from_surface_tree;
1011 use smithay::desktop::{Window, WindowSurfaceType};
1112 use smithay::input::keyboard::{Keycode, XkbConfig};
@@ -212,6 +213,7 @@ impl State {
212213 crate::backend::Backend::Starting => {}
213214 }
214215 self.wm.prune(now_ns());
216+ let _ = self.renderer.cleanup_texture_cache();
215217 self.confirm_lock();
216218 self.complete_captures();
217219 if std::mem::take(&mut self.dirty.snapshot) {
Modified file: crates/render-vk/src/device.rs+4 additions−1 deletions
@@ -1,5 +1,6 @@
11 use crate::Error;
22 use ash::vk;
3+use gpu_allocator::AllocationSizes;
34 use gpu_allocator::vulkan::{Allocator, AllocatorCreateDesc};
45 use std::sync::Mutex;
56
@@ -200,7 +201,9 @@ impl Shared {
200201 physical_device: physical,
201202 debug_settings: Default::default(),
202203 buffer_device_address: false,
203- allocation_sizes: Default::default(),
204+ // Host blocks are pinned system RAM that stays resident while any
205+ // allocation lives in them, and the default 64 MB block is mostly idle.
206+ allocation_sizes: AllocationSizes::new(256 << 20, 4 << 20),
204207 });
205208 let device = Device {
206209 _entry: entry,
Modified file: crates/render-vk/src/image.rs+31 additions−1 deletions
@@ -9,6 +9,7 @@ use smithay::backend::renderer::{Texture, TextureMapping};
99 use std::fmt;
1010 use std::marker::PhantomData;
1111 use std::sync::{Arc, Mutex};
12+use std::time::{Duration, Instant};
1213
1314 pub(crate) enum Memory {
1415 Allocated(Allocation),
@@ -200,10 +201,38 @@ pub(crate) struct Pooled {
200201 size: usize,
201202 usage: vk::BufferUsageFlags,
202203 location: MemoryLocation,
204+ returned: Instant,
203205 }
204206
205207 /// Pooled staging memory kept at most, past which dropped buffers are freed.
206-const POOL_BYTES: usize = 96 * 1024 * 1024;
208+const POOL_BYTES: usize = 32 * 1024 * 1024;
209+
210+/// How long a pooled buffer may go unused before it is freed.
211+const POOL_IDLE: Duration = Duration::from_secs(2);
212+
213+/// Frees pooled staging buffers that have sat unused for [`POOL_IDLE`].
214+pub(crate) fn trim_staging(shared: &Shared) {
215+ let now = Instant::now();
216+ let expired: Vec<Pooled> = {
217+ let mut pool = shared
218+ .staging_pool
219+ .lock()
220+ .unwrap_or_else(|e| e.into_inner());
221+ let (stale, kept) = std::mem::take(&mut *pool)
222+ .into_iter()
223+ .partition(|p| now - p.returned >= POOL_IDLE);
224+ *pool = kept;
225+ stale
226+ };
227+ if expired.is_empty() {
228+ return;
229+ }
230+ let mut allocator = shared.allocator.lock().unwrap_or_else(|e| e.into_inner());
231+ for p in expired {
232+ unsafe { shared.device.device.destroy_buffer(p.buffer, None) };
233+ let _ = allocator.free(p.allocation);
234+ }
235+}
207236
208237 impl Staging {
209238 pub fn new(
@@ -304,6 +333,7 @@ impl Drop for Staging {
304333 size: self.size,
305334 usage: self.usage,
306335 location: self.location,
336+ returned: Instant::now(),
307337 });
308338 return;
309339 }
Modified file: crates/render-vk/src/renderer/mod.rs+3 additions
@@ -23,6 +23,7 @@ use smithay::backend::renderer::{
2323 Bind, ContextId, DebugFlags, ExportMem, ImportDma, ImportDmaWl, ImportMem, Offscreen, Renderer,
2424 RendererSuper, Texture, TextureFilter,
2525 };
26+use smithay::reexports::wayland_server::Resource;
2627 use smithay::reexports::wayland_server::backend::ObjectId;
2728 use smithay::reexports::wayland_server::protocol::wl_buffer::WlBuffer;
2829 use smithay::utils::{Buffer, Physical, Rectangle, Size, Transform};
@@ -185,6 +186,8 @@ impl VulkanRenderer {
185186 });
186187 self.dmabuf_textures.retain(|k, _| !k.is_gone());
187188 self.dmabuf_targets.retain(|k, _| !k.is_gone());
189+ self.staged.retain(|_, (b, _)| b.is_alive());
190+ crate::image::trim_staging(&self.shared);
188191 }
189192
190193 fn begin(&mut self) -> Result<vk::CommandBuffer, Error> {