e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 1 | use crate::Error; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 2 | use crate::device::Shared; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 3 | use ash::vk; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 4 | use gpu_allocator::MemoryLocation; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 5 | use gpu_allocator::vulkan::{Allocation, AllocationCreateDesc, AllocationScheme}; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 6 | use std::sync::{Arc, Mutex}; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 7 | use std::time::{Duration, Instant}; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 8 | |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 9 | /// Pooled staging memory kept at most, past which dropped buffers are freed. |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 10 | const POOL_BYTES: usize = 32 * 1024 * 1024; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 11 | |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 12 | /// How long a pooled buffer may go unused before it is freed. |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 13 | const POOL_IDLE: Duration = Duration::from_secs(2); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 14 | |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 15 | struct Pooled { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 16 | buffer: vk::Buffer, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 17 | allocation: Allocation, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 18 | size: usize, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 19 | usage: vk::BufferUsageFlags, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 20 | location: MemoryLocation, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 21 | returned: Instant, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 22 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 23 | |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 24 | /// Staging buffers kept for reuse, see [`Staging`]. |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 25 | pub(crate) struct StagingPool { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 26 | shared: Arc<Shared>, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 27 | free: Mutex<Vec<Pooled>>, |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 28 | /// Granularity of flushes and invalidations of non-coherent memory. |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 29 | atom: u64, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 30 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 31 | |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 32 | impl StagingPool { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 33 | pub fn new(shared: &Arc<Shared>) -> Arc<Self> { |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 34 | let limits = unsafe { |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 35 | shared |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 36 | .device |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 37 | .instance |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 38 | .get_physical_device_properties(shared.device.physical) |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 39 | } |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 40 | .limits; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 41 | Arc::new(Self { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 42 | shared: shared.clone(), |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 43 | free: Mutex::new(Vec::new()), |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 44 | atom: limits.non_coherent_atom_size.max(1), |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 45 | }) |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 46 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 47 | |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 48 | /// Frees pooled buffers that have sat unused for [`POOL_IDLE`]. |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 49 | pub fn trim(&self) { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 50 | let now = Instant::now(); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 51 | let expired: Vec<Pooled> = self |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 52 | .free |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 53 | .lock() |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 54 | .unwrap_or_else(|e| e.into_inner()) |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 55 | .extract_if(.., |p| now - p.returned >= POOL_IDLE) |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 56 | .collect(); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 57 | self.destroy(expired.into_iter().map(|p| (p.buffer, p.allocation))); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 58 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 59 | |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 60 | fn destroy(&self, buffers: impl IntoIterator<Item = (vk::Buffer, Allocation)>) { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 61 | let mut buffers = buffers.into_iter().peekable(); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 62 | if buffers.peek().is_none() { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 63 | return; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 64 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 65 | let mut allocator = self |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 66 | .shared |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 67 | .allocator |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 68 | .lock() |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 69 | .unwrap_or_else(|e| e.into_inner()); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 70 | for (buffer, allocation) in buffers { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 71 | unsafe { self.shared.device.device.destroy_buffer(buffer, None) }; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 72 | let _ = allocator.free(allocation); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 73 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 74 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 75 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 76 | |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 77 | impl Drop for StagingPool { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 78 | fn drop(&mut self) { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 79 | let free = std::mem::take(self.free.get_mut().unwrap_or_else(|e| e.into_inner())); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 80 | self.destroy(free.into_iter().map(|p| (p.buffer, p.allocation))); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 81 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 82 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 83 | |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 84 | /// A host-visible buffer for uploads and readbacks. Dropped ones go back to |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 85 | /// a pool instead of being freed. Allocating and freeing large host-visible |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 86 | /// memory takes a driver lock on NVIDIA that `vkQueueSubmit` also waits on, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 87 | /// so a staging buffer made per upload on the import worker stalled the main |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 88 | /// thread's submits for 1 to 3 ms. |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 89 | pub(crate) struct Staging { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 90 | pub pool: Arc<StagingPool>, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 91 | pub buffer: vk::Buffer, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 92 | allocation: Option<Allocation>, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 93 | size: usize, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 94 | usage: vk::BufferUsageFlags, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 95 | location: MemoryLocation, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 96 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 97 | |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 98 | impl Staging { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 99 | pub fn new( |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 100 | pool: &Arc<StagingPool>, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 101 | size: usize, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 102 | usage: vk::BufferUsageFlags, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 103 | location: MemoryLocation, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 104 | ) -> Result<Self, Error> { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 105 | let reused = { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 106 | let mut free = pool.free.lock().unwrap_or_else(|e| e.into_inner()); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 107 | let fits = |p: &Pooled| { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 108 | p.usage == usage && p.location == location && p.size >= size && p.size <= size * 2 |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 109 | }; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 110 | free.iter().position(fits).map(|i| free.swap_remove(i)) |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 111 | }; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 112 | if let Some(p) = reused { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 113 | return Ok(Self { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 114 | pool: pool.clone(), |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 115 | buffer: p.buffer, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 116 | allocation: Some(p.allocation), |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 117 | size: p.size, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 118 | usage, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 119 | location, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 120 | }); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 121 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 122 | let d = &pool.shared.device.device; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 123 | let buffer = unsafe { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 124 | d.create_buffer( |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 125 | &vk::BufferCreateInfo::default() |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 126 | .size(size as u64) |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 127 | .usage(usage), |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 128 | None, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 129 | )? |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 130 | }; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 131 | let requirements = unsafe { d.get_buffer_memory_requirements(buffer) }; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 132 | let allocation = pool |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 133 | .shared |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 134 | .allocator |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 135 | .lock() |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 136 | .unwrap_or_else(|e| e.into_inner()) |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 137 | .allocate(&AllocationCreateDesc { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 138 | name: "staging", |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 139 | requirements, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 140 | location, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 141 | linear: true, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 142 | allocation_scheme: AllocationScheme::GpuAllocatorManaged, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 143 | }); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 144 | let allocation = match allocation { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 145 | Ok(a) => a, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 146 | Err(e) => { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 147 | unsafe { d.destroy_buffer(buffer, None) }; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 148 | return Err(e.into()); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 149 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 150 | }; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 151 | unsafe { d.bind_buffer_memory(buffer, allocation.memory(), allocation.offset())? }; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 152 | Ok(Self { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 153 | pool: pool.clone(), |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 154 | buffer, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 155 | allocation: Some(allocation), |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 156 | size, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 157 | usage, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 158 | location, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 159 | }) |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 160 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 161 | |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 162 | /// The mapped bytes, with whatever the GPU wrote to them made visible. |
acf5e9848529 | atagen | 2026-10-19 07:27 UTC | 163 | pub fn bytes(&self) -> Result<&[u8], Error> { |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 164 | self.host_sync(false)?; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 165 | self.allocation |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 166 | .as_ref() |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 167 | .and_then(|a| a.mapped_slice()) |
acf5e9848529 | atagen | 2026-10-19 07:27 UTC | 168 | .ok_or(Error::StagingUnmapped) |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 169 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 170 | |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 171 | /// Makes what the host wrote through `bytes_mut` visible to the GPU. |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 172 | pub fn flush(&self) -> Result<(), Error> { |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 173 | self.host_sync(true) |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 174 | } |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 175 | |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 176 | /// Flushes or invalidates the mapping. Coherent memory needs neither. |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 177 | fn host_sync(&self, flush: bool) -> Result<(), Error> { |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 178 | let Some(allocation) = self.allocation.as_ref() else { |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 179 | return Ok(()); |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 180 | }; |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 181 | if allocation |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 182 | .memory_properties() |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 183 | .contains(vk::MemoryPropertyFlags::HOST_COHERENT) |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 184 | { |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 185 | return Ok(()); |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 186 | } |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 187 | let atom = self.pool.atom; |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 188 | let range = [vk::MappedMemoryRange::default() |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 189 | .memory(unsafe { allocation.memory() }) |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 190 | .offset(allocation.offset() / atom * atom) |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 191 | .size(vk::WHOLE_SIZE)]; |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 192 | let d = &self.pool.shared.device.device; |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 193 | unsafe { |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 194 | if flush { |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 195 | d.flush_mapped_memory_ranges(&range)?; |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 196 | } else { |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 197 | d.invalidate_mapped_memory_ranges(&range)?; |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 198 | } |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 199 | } |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 200 | Ok(()) |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 201 | } |
f8e6bc3e5529 | atagen | 2026-10-19 07:52 UTC | 202 | |
acf5e9848529 | atagen | 2026-10-19 07:27 UTC | 203 | pub fn bytes_mut(&mut self) -> Result<&mut [u8], Error> { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 204 | self.allocation |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 205 | .as_mut() |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 206 | .and_then(|a| a.mapped_slice_mut()) |
acf5e9848529 | atagen | 2026-10-19 07:27 UTC | 207 | .ok_or(Error::StagingUnmapped) |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 208 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 209 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 210 | |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 211 | impl Drop for Staging { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 212 | fn drop(&mut self) { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 213 | let Some(allocation) = self.allocation.take() else { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 214 | return; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 215 | }; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 216 | let mut free = self.pool.free.lock().unwrap_or_else(|e| e.into_inner()); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 217 | let pooled: usize = free.iter().map(|p| p.size).sum(); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 218 | if pooled + self.size <= POOL_BYTES { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 219 | free.push(Pooled { |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 220 | buffer: self.buffer, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 221 | allocation, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 222 | size: self.size, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 223 | usage: self.usage, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 224 | location: self.location, |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 225 | returned: Instant::now(), |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 226 | }); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 227 | return; |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 228 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 229 | drop(free); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 230 | self.pool.destroy([(self.buffer, allocation)]); |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 231 | } |
e0b486d6097f | atagen | 2026-10-19 07:26 UTC | 232 | } |