@@ -3,6 +3,7 @@ use crate::hub::HUB;
3
3
use crate :: track:: { TrackerSet , TrackPermit } ;
4
4
use crate :: {
5
5
LifeGuard , RefCount , Stored , SubmissionIndex , WeaklyStored ,
6
+ BufferMapAsyncStatus , BufferMapOperation ,
6
7
} ;
7
8
use crate :: {
8
9
BufferId , CommandBufferId , AdapterId , DeviceId , QueueId ,
@@ -11,7 +12,7 @@ use crate::{
11
12
#[ cfg( feature = "local" ) ]
12
13
use crate :: {
13
14
BindGroupId , BindGroupLayoutId , PipelineLayoutId , SamplerId , SwapChainId ,
14
- ShaderModuleId , CommandEncoderId , RenderPipelineId , ComputePipelineId ,
15
+ ShaderModuleId , CommandEncoderId , RenderPipelineId , ComputePipelineId ,
15
16
} ;
16
17
17
18
use back;
@@ -83,9 +84,12 @@ struct ActiveSubmission<B: hal::Backend> {
83
84
index : SubmissionIndex ,
84
85
fence : B :: Fence ,
85
86
resources : Vec < Resource < B > > ,
87
+ mapped : Vec < BufferId > ,
86
88
}
87
89
88
90
struct DestroyedResources < B : hal:: Backend > {
91
+ /// Resources that the user has requested be mapped, but are still in use.
92
+ mapped : Vec < Stored < BufferId > > ,
89
93
/// Resources that are destroyed by the user but still referenced by
90
94
/// other objects or command buffers.
91
95
referenced : Vec < ( ResourceId , RefCount ) > ,
@@ -95,17 +99,22 @@ struct DestroyedResources<B: hal::Backend> {
95
99
/// Resources that are neither referenced or used, just pending
96
100
/// actual deletion.
97
101
free : Vec < Resource < B > > ,
102
+ ready_to_map : Vec < BufferId > ,
98
103
}
99
104
100
105
unsafe impl < B : hal:: Backend > Send for DestroyedResources < B > { }
101
106
unsafe impl < B : hal:: Backend > Sync for DestroyedResources < B > { }
102
107
103
108
impl < B : hal:: Backend > DestroyedResources < B > {
104
- fn add ( & mut self , resource_id : ResourceId , ref_count : RefCount ) {
109
+ fn destroy ( & mut self , resource_id : ResourceId , ref_count : RefCount ) {
105
110
debug_assert ! ( !self . referenced. iter( ) . any( |r| r. 0 == resource_id) ) ;
106
111
self . referenced . push ( ( resource_id, ref_count) ) ;
107
112
}
108
113
114
+ fn map ( & mut self , buffer : BufferId , ref_count : RefCount ) {
115
+ self . mapped . push ( Stored { value : buffer, ref_count} ) ;
116
+ }
117
+
109
118
/// Returns the last submission index that is done.
110
119
fn cleanup ( & mut self , raw : & B :: Device ) -> SubmissionIndex {
111
120
let mut last_done = 0 ;
@@ -185,9 +194,63 @@ impl DestroyedResources<back::Backend> {
185
194
}
186
195
}
187
196
}
197
+
198
+ let buffer_guard = HUB . buffers . read ( ) ;
199
+
200
+ for i in ( 0 ..self . mapped . len ( ) ) . rev ( ) {
201
+ // one in resource itself, one here in this list, one the owner holds, and one more somewhere?
202
+ let num_refs = self . mapped [ i] . ref_count . load ( ) ;
203
+ trace ! ( "{} references remain" , num_refs) ;
204
+ if num_refs <= 4 {
205
+ // assert_eq!(num_refs, 4);
206
+ let resource_id = self . mapped . swap_remove ( i) . value ;
207
+ let buf = buffer_guard. get ( resource_id) ;
208
+ let submit_index = buf. life_guard . submission_index . load ( Ordering :: Acquire ) ;
209
+ match self
210
+ . active
211
+ . iter_mut ( )
212
+ . find ( |a| a. index == submit_index)
213
+ {
214
+ Some ( a) => a. mapped . push ( resource_id) ,
215
+ None => self . ready_to_map . push ( resource_id) ,
216
+ }
217
+ }
218
+ }
188
219
}
189
- }
190
220
221
+ fn handle_mapping ( & mut self , raw : & <back:: Backend as hal:: Backend >:: Device ) {
222
+ let mut buffer_guard = HUB . buffers . write ( ) ;
223
+
224
+ for buffer_id in self . ready_to_map . drain ( ..) {
225
+ let mut buffer = buffer_guard. get_mut ( buffer_id) ;
226
+ let mut operation = None ;
227
+ std:: mem:: swap ( & mut operation, & mut buffer. pending_map_operation ) ;
228
+ match operation {
229
+ Some ( BufferMapOperation :: Read ( range, callback, userdata) ) => {
230
+ if let Ok ( ptr) = unsafe { raw. map_memory ( & buffer. memory , range. clone ( ) ) } {
231
+ if !buffer. memory_properties . contains ( hal:: memory:: Properties :: COHERENT ) {
232
+ unsafe { raw. invalidate_mapped_memory_ranges ( iter:: once ( ( & buffer. memory , range. clone ( ) ) ) ) . unwrap ( ) } ; // TODO
233
+ }
234
+ callback ( BufferMapAsyncStatus :: Success , ptr, userdata) ;
235
+ } else {
236
+ callback ( BufferMapAsyncStatus :: Error , std:: ptr:: null ( ) , userdata) ;
237
+ }
238
+ } ,
239
+ Some ( BufferMapOperation :: Write ( range, callback, userdata) ) => {
240
+ if let Ok ( ptr) = unsafe { raw. map_memory ( & buffer. memory , range. clone ( ) ) } {
241
+ if !buffer. memory_properties . contains ( hal:: memory:: Properties :: COHERENT ) {
242
+ buffer. mapped_write_ranges . push ( range) ;
243
+ }
244
+ callback ( BufferMapAsyncStatus :: Success , ptr, userdata) ;
245
+ } else {
246
+ callback ( BufferMapAsyncStatus :: Error , std:: ptr:: null_mut ( ) , userdata) ;
247
+ }
248
+ } ,
249
+ _ => unreachable ! ( ) ,
250
+ } ;
251
+ }
252
+ }
253
+ }
191
254
192
255
pub struct Device < B : hal:: Backend > {
193
256
pub ( crate ) raw : B :: Device ,
@@ -276,9 +339,11 @@ impl<B: hal::Backend> Device<B> {
276
339
framebuffers : Mutex :: new ( FastHashMap :: default ( ) ) ,
277
340
desc_pool,
278
341
destroyed : Mutex :: new ( DestroyedResources {
342
+ mapped : Vec :: new ( ) ,
279
343
referenced : Vec :: new ( ) ,
280
344
active : Vec :: new ( ) ,
281
345
free : Vec :: new ( ) ,
346
+ ready_to_map : Vec :: new ( ) ,
282
347
} ) ,
283
348
}
284
349
}
@@ -296,7 +361,7 @@ pub fn device_create_buffer(
296
361
) -> resource:: Buffer < back:: Backend > {
297
362
let device_guard = HUB . devices . read ( ) ;
298
363
let device = & device_guard. get ( device_id) ;
299
- let ( usage, _ ) = conv:: map_buffer_usage ( desc. usage ) ;
364
+ let ( usage, memory_properties ) = conv:: map_buffer_usage ( desc. usage ) ;
300
365
301
366
let mut buffer = unsafe {
302
367
device. raw . create_buffer ( desc. size as u64 , usage) . unwrap ( )
@@ -310,11 +375,10 @@ pub fn device_create_buffer(
310
375
. iter ( )
311
376
. enumerate ( )
312
377
. position ( |( id, memory_type) | {
313
- // TODO
314
378
requirements. type_mask & ( 1 << id) != 0
315
379
&& memory_type
316
380
. properties
317
- . contains ( hal :: memory :: Properties :: DEVICE_LOCAL )
381
+ . contains ( memory_properties )
318
382
} )
319
383
. unwrap ( )
320
384
. into ( ) ;
@@ -336,6 +400,10 @@ pub fn device_create_buffer(
336
400
value : device_id,
337
401
ref_count : device. life_guard . ref_count . clone ( ) ,
338
402
} ,
403
+ memory_properties,
404
+ memory,
405
+ mapped_write_ranges : Vec :: new ( ) ,
406
+ pending_map_operation : None ,
339
407
life_guard : LifeGuard :: new ( ) ,
340
408
}
341
409
}
@@ -377,13 +445,12 @@ pub extern "C" fn wgpu_buffer_destroy(buffer_id: BufferId) {
377
445
. get ( buffer. device_id . value )
378
446
. destroyed
379
447
. lock ( )
380
- . add (
448
+ . destroy (
381
449
ResourceId :: Buffer ( buffer_id) ,
382
450
buffer. life_guard . ref_count . clone ( ) ,
383
451
) ;
384
452
}
385
453
386
-
387
454
pub fn device_create_texture (
388
455
device_id : DeviceId ,
389
456
desc : & resource:: TextureDescriptor ,
@@ -618,7 +685,7 @@ pub extern "C" fn wgpu_texture_destroy(texture_id: TextureId) {
618
685
. get ( texture. device_id . value )
619
686
. destroyed
620
687
. lock ( )
621
- . add (
688
+ . destroy (
622
689
ResourceId :: Texture ( texture_id) ,
623
690
texture. life_guard . ref_count . clone ( ) ,
624
691
) ;
@@ -637,7 +704,7 @@ pub extern "C" fn wgpu_texture_view_destroy(texture_view_id: TextureViewId) {
637
704
. get ( device_id)
638
705
. destroyed
639
706
. lock ( )
640
- . add (
707
+ . destroy (
641
708
ResourceId :: TextureView ( texture_view_id) ,
642
709
view. life_guard . ref_count . clone ( ) ,
643
710
) ;
@@ -1047,11 +1114,13 @@ pub extern "C" fn wgpu_queue_submit(
1047
1114
let mut destroyed = device. destroyed . lock ( ) ;
1048
1115
destroyed. triage_referenced ( & mut * trackers) ;
1049
1116
let last_done = destroyed. cleanup ( & device. raw ) ;
1117
+ destroyed. handle_mapping ( & device. raw ) ;
1050
1118
1051
1119
destroyed. active . push ( ActiveSubmission {
1052
1120
index : old_submit_index + 1 ,
1053
1121
fence,
1054
1122
resources : Vec :: new ( ) ,
1123
+ mapped : Vec :: new ( ) ,
1055
1124
} ) ;
1056
1125
1057
1126
last_done
@@ -1386,8 +1455,8 @@ pub fn device_create_swap_chain(
1386
1455
let mut destroyed = device. destroyed . lock ( ) ;
1387
1456
assert_eq ! ( old. device_id. value, device_id) ;
1388
1457
for frame in old. frames {
1389
- destroyed. add ( ResourceId :: Texture ( frame. texture_id . value ) , frame. texture_id . ref_count ) ;
1390
- destroyed. add ( ResourceId :: TextureView ( frame. view_id . value ) , frame. view_id . ref_count ) ;
1458
+ destroyed. destroy ( ResourceId :: Texture ( frame. texture_id . value ) , frame. texture_id . ref_count ) ;
1459
+ destroyed. destroy ( ResourceId :: TextureView ( frame. view_id . value ) , frame. view_id . ref_count ) ;
1391
1460
}
1392
1461
unsafe {
1393
1462
old. command_pool . reset ( )
@@ -1610,4 +1679,62 @@ pub extern "C" fn wgpu_buffer_set_sub_data(
1610
1679
#[ no_mangle]
1611
1680
pub extern "C" fn wgpu_device_destroy ( device_id : BufferId ) {
1612
1681
HUB . devices . unregister ( device_id) ;
1682
+ }
1683
+
1684
+ pub type BufferMapReadCallback = extern "C" fn ( status : BufferMapAsyncStatus , data : * const u8 , userdata : * mut u8 ) ;
1685
+ pub type BufferMapWriteCallback = extern "C" fn ( status : BufferMapAsyncStatus , data : * mut u8 , userdata : * mut u8 ) ;
1686
+
1687
+ #[ no_mangle]
1688
+ pub extern "C" fn wgpu_buffer_map_read_async (
1689
+ buffer_id : BufferId ,
1690
+ start : u32 , size : u32 , callback : BufferMapReadCallback , userdata : * mut u8 ,
1691
+ ) {
1692
+ let mut buffer_guard = HUB . buffers . write ( ) ;
1693
+ let buffer = buffer_guard. get_mut ( buffer_id) ;
1694
+ let device_guard = HUB . devices . read ( ) ;
1695
+ let device = device_guard. get ( buffer. device_id . value ) ;
1696
+
1697
+ let range = start as u64 ..( start + size) as u64 ;
1698
+ buffer. pending_map_operation = Some ( BufferMapOperation :: Read ( range, callback, userdata) ) ;
1699
+
1700
+ device
1701
+ . destroyed
1702
+ . lock ( )
1703
+ . map ( buffer_id, buffer. life_guard . ref_count . clone ( ) ) ;
1704
+ }
1705
+
1706
+ #[ no_mangle]
1707
+ pub extern "C" fn wgpu_buffer_map_write_async (
1708
+ buffer_id : BufferId ,
1709
+ start : u32 , size : u32 , callback : BufferMapWriteCallback , userdata : * mut u8 ,
1710
+ ) {
1711
+ let mut buffer_guard = HUB . buffers . write ( ) ;
1712
+ let buffer = buffer_guard. get_mut ( buffer_id) ;
1713
+ let device_guard = HUB . devices . read ( ) ;
1714
+ let device = device_guard. get ( buffer. device_id . value ) ;
1715
+
1716
+ let range = start as u64 ..( start + size) as u64 ;
1717
+ buffer. pending_map_operation = Some ( BufferMapOperation :: Write ( range, callback, userdata) ) ;
1718
+
1719
+ device
1720
+ . destroyed
1721
+ . lock ( )
1722
+ . map ( buffer_id, buffer. life_guard . ref_count . clone ( ) ) ;
1723
+ }
1724
+
1725
+ #[ no_mangle]
1726
+ pub extern "C" fn wgpu_buffer_unmap (
1727
+ buffer_id : BufferId ,
1728
+ ) {
1729
+ let mut buffer_guard = HUB . buffers . write ( ) ;
1730
+ let buffer = buffer_guard. get_mut ( buffer_id) ;
1731
+ let mut device_guard = HUB . devices . write ( ) ;
1732
+ let device = device_guard. get_mut ( buffer. device_id . value ) ;
1733
+
1734
+ if !buffer. mapped_write_ranges . is_empty ( ) {
1735
+ unsafe { device. raw . flush_mapped_memory_ranges ( buffer. mapped_write_ranges . iter ( ) . map ( |r| { ( & buffer. memory , r. clone ( ) ) } ) ) . unwrap ( ) } ; // TODO
1736
+ buffer. mapped_write_ranges . clear ( ) ;
1737
+ }
1738
+
1739
+ unsafe { device. raw . unmap_memory ( & buffer. memory ) } ;
1613
1740
}
0 commit comments