1- use std:: sync:: Arc ;
1+ use std:: ops:: Deref ;
2+ use std:: sync:: { Arc , Mutex } ;
23use std:: time:: Instant ;
34use tokio:: sync:: oneshot;
45use wgpu:: COPY_BYTES_PER_ROW_ALIGNMENT ;
@@ -8,24 +9,91 @@ use crate::{ProjectUniforms, RenderingError};
89const GPU_BUFFER_WAIT_TIMEOUT_SECS : u64 = 10 ;
910
1011pub 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
1476impl 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
409476pub 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