Skip to content

Commit 0ac3c47

Browse files
committed
feat(rendering): add SharedNv12Buffer with pool-based buffer recycling
1 parent 138f7cd commit 0ac3c47

1 file changed

Lines changed: 83 additions & 16 deletions

File tree

crates/rendering/src/frame_pipeline.rs

Lines changed: 83 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use std::sync::Arc;
1+
use std::ops::Deref;
2+
use std::sync::{Arc, Mutex};
23
use std::time::Instant;
34
use tokio::sync::oneshot;
45
use wgpu::COPY_BYTES_PER_ROW_ALIGNMENT;
@@ -8,24 +9,91 @@ use crate::{ProjectUniforms, RenderingError};
89
const GPU_BUFFER_WAIT_TIMEOUT_SECS: u64 = 10;
910

1011
pub struct NV12BufferPool {
11-
buffers: Vec<Vec<u8>>,
12+
buffers: Arc<Mutex<Vec<Vec<u8>>>>,
13+
}
14+
15+
struct PooledNv12Buffer {
16+
data: Vec<u8>,
17+
pool: Option<Arc<Mutex<Vec<Vec<u8>>>>>,
18+
}
19+
20+
impl Drop for PooledNv12Buffer {
21+
fn drop(&mut self) {
22+
let Some(pool) = self.pool.take() else {
23+
return;
24+
};
25+
26+
let mut data = std::mem::take(&mut self.data);
27+
data.clear();
28+
29+
if let Ok(mut buffers) = pool.lock() {
30+
buffers.push(data);
31+
}
32+
}
33+
}
34+
35+
#[derive(Clone)]
36+
pub struct SharedNv12Buffer(Arc<PooledNv12Buffer>);
37+
38+
impl SharedNv12Buffer {
39+
fn new(data: Vec<u8>, pool: Option<Arc<Mutex<Vec<Vec<u8>>>>>) -> Self {
40+
Self(Arc::new(PooledNv12Buffer { data, pool }))
41+
}
42+
43+
pub fn from_vec(data: Vec<u8>) -> Self {
44+
Self::new(data, None)
45+
}
46+
47+
pub fn from_arc_vec(data: Arc<Vec<u8>>) -> Self {
48+
Self::from_vec(Arc::unwrap_or_clone(data))
49+
}
50+
51+
pub fn into_vec(self) -> Vec<u8> {
52+
match Arc::try_unwrap(self.0) {
53+
Ok(mut inner) => {
54+
inner.pool = None;
55+
std::mem::take(&mut inner.data)
56+
}
57+
Err(shared) => shared.data.clone(),
58+
}
59+
}
60+
}
61+
62+
impl AsRef<[u8]> for SharedNv12Buffer {
63+
fn as_ref(&self) -> &[u8] {
64+
&self.0.data
65+
}
66+
}
67+
68+
impl Deref for SharedNv12Buffer {
69+
type Target = [u8];
70+
71+
fn deref(&self) -> &Self::Target {
72+
&self.0.data
73+
}
1274
}
1375

1476
impl NV12BufferPool {
1577
pub fn new(pre_alloc: usize) -> Self {
1678
Self {
17-
buffers: Vec::with_capacity(pre_alloc),
79+
buffers: Arc::new(Mutex::new(Vec::with_capacity(pre_alloc))),
1880
}
1981
}
2082

21-
pub fn acquire(&mut self, size: usize) -> Vec<u8> {
22-
if let Some(pos) = self.buffers.iter().position(|b| b.capacity() >= size) {
23-
let mut buf = self.buffers.swap_remove(pos);
83+
pub fn acquire(&self, size: usize) -> Vec<u8> {
84+
if let Ok(mut buffers) = self.buffers.lock()
85+
&& let Some(pos) = buffers.iter().position(|b| b.capacity() >= size)
86+
{
87+
let mut buf = buffers.swap_remove(pos);
2488
buf.clear();
25-
buf
26-
} else {
27-
Vec::with_capacity(size)
89+
return buf;
2890
}
91+
92+
Vec::with_capacity(size)
93+
}
94+
95+
pub fn wrap(&self, data: Vec<u8>) -> SharedNv12Buffer {
96+
SharedNv12Buffer::new(data, Some(Arc::clone(&self.buffers)))
2997
}
3098
}
3199

@@ -373,14 +441,13 @@ impl PendingNv12Readback {
373441
let data = buffer_slice.get_mapped_range();
374442
let data_len = data.len();
375443

376-
let nv12_vec = if let Some(pool) = buffer_pool {
444+
let nv12_data = if let Some(pool) = buffer_pool {
377445
let mut buf = pool.acquire(data_len);
378446
buf.extend_from_slice(&data);
379-
buf
447+
pool.wrap(buf)
380448
} else {
381-
data.to_vec()
449+
SharedNv12Buffer::from_vec(data.to_vec())
382450
};
383-
let nv12_data = Arc::new(nv12_vec);
384451

385452
drop(data);
386453
self.buffer.unmap();
@@ -407,7 +474,7 @@ pub enum GpuOutputFormat {
407474
}
408475

409476
pub struct Nv12RenderedFrame {
410-
pub data: Arc<Vec<u8>>,
477+
pub data: SharedNv12Buffer,
411478
pub width: u32,
412479
pub height: u32,
413480
pub y_stride: u32,
@@ -430,7 +497,7 @@ impl Nv12RenderedFrame {
430497
}
431498

432499
pub fn into_data(self) -> Vec<u8> {
433-
Arc::unwrap_or_clone(self.data)
500+
self.data.into_vec()
434501
}
435502

436503
pub fn y_plane(&self) -> &[u8] {
@@ -948,7 +1015,7 @@ pub async fn finish_encoder_nv12_pooled(
9481015
} else {
9491016
let rgba_frame = finish_encoder(session, device, queue, uniforms, encoder).await?;
9501017
Ok(rgba_frame.map(|f| Nv12RenderedFrame {
951-
data: f.data,
1018+
data: SharedNv12Buffer::from_arc_vec(f.data),
9521019
width: f.width,
9531020
height: f.height,
9541021
y_stride: f.padded_bytes_per_row,

0 commit comments

Comments
 (0)