@@ -213,20 +213,22 @@ impl DestroyedResources<back::Backend> {
213213 let buffer_guard = HUB . buffers . read ( ) ;
214214
215215 for i in ( 0 ..self . mapped . len ( ) ) . rev ( ) {
216- // one in resource itself, one here in this list, one the owner holds, and one more somewhere?
217- let num_refs = self . mapped [ i] . ref_count . load ( ) ;
218- trace ! ( "{} references remain" , num_refs) ;
219- if num_refs <= 4 {
220- // assert_eq!(num_refs, 4);
221- let resource_id = self . mapped . swap_remove ( i) . value ;
222- let buf = & buffer_guard[ resource_id] ;
223- let submit_index = buf. life_guard . submission_index . load ( Ordering :: Acquire ) ;
224- self . active
225- . iter_mut ( )
226- . find ( |a| a. index == submit_index)
227- . map_or ( & mut self . ready_to_map , |a| & mut a. mapped )
228- . push ( resource_id) ;
229- }
216+ let resource_id = self . mapped . swap_remove ( i) . value ;
217+ let buf = & buffer_guard[ resource_id] ;
218+
219+ let usage = match buf. pending_map_operation {
220+ Some ( BufferMapOperation :: Read ( ..) ) => resource:: BufferUsageFlags :: MAP_READ ,
221+ Some ( BufferMapOperation :: Write ( ..) ) => resource:: BufferUsageFlags :: MAP_WRITE ,
222+ _ => unreachable ! ( ) ,
223+ } ;
224+ trackers. buffers . get_with_replaced_usage ( & buffer_guard, resource_id, usage) . unwrap ( ) ;
225+
226+ let submit_index = buf. life_guard . submission_index . load ( Ordering :: Acquire ) ;
227+ self . active
228+ . iter_mut ( )
229+ . find ( |a| a. index == submit_index)
230+ . map_or ( & mut self . ready_to_map , |a| & mut a. mapped )
231+ . push ( resource_id) ;
230232 }
231233 }
232234
@@ -269,34 +271,39 @@ impl DestroyedResources<back::Backend> {
269271 }
270272
271273 fn handle_mapping ( & mut self , raw : & <back:: Backend as hal:: Backend >:: Device ) {
272- let mut buffer_guard = HUB . buffers . write ( ) ;
273-
274274 for buffer_id in self . ready_to_map . drain ( ..) {
275- let buffer = & mut buffer_guard[ buffer_id] ;
276275 let mut operation = None ;
277- std:: mem:: swap ( & mut operation, & mut buffer. pending_map_operation ) ;
278- match operation {
279- Some ( BufferMapOperation :: Read ( range, callback, userdata) ) => {
280- if let Ok ( ptr) = unsafe { raw. map_memory ( & buffer. memory , range. clone ( ) ) } {
281- if !buffer. memory_properties . contains ( hal:: memory:: Properties :: COHERENT ) {
282- unsafe { raw. invalidate_mapped_memory_ranges ( iter:: once ( ( & buffer. memory , range. clone ( ) ) ) ) . unwrap ( ) } ; // TODO
276+ let ( result, ptr) = {
277+ let mut buffer_guard = HUB . buffers . write ( ) ;
278+ let buffer = & mut buffer_guard[ buffer_id] ;
279+ std:: mem:: swap ( & mut operation, & mut buffer. pending_map_operation ) ;
280+ match operation. clone ( ) . unwrap ( ) {
281+ BufferMapOperation :: Read ( range, ..) => {
282+ if let Ok ( ptr) = unsafe { raw. map_memory ( & buffer. memory , range. clone ( ) ) } {
283+ if !buffer. memory_properties . contains ( hal:: memory:: Properties :: COHERENT ) {
284+ unsafe { raw. invalidate_mapped_memory_ranges ( iter:: once ( ( & buffer. memory , range. clone ( ) ) ) ) . unwrap ( ) } ; // TODO
285+ }
286+ ( BufferMapAsyncStatus :: Success , Some ( ptr) )
287+ } else {
288+ ( BufferMapAsyncStatus :: Error , None )
283289 }
284- callback ( BufferMapAsyncStatus :: Success , ptr , userdata ) ;
285- } else {
286- callback ( BufferMapAsyncStatus :: Error , std :: ptr :: null ( ) , userdata ) ;
287- }
288- } ,
289- Some ( BufferMapOperation :: Write ( range , callback , userdata ) ) => {
290- if let Ok ( ptr ) = unsafe { raw . map_memory ( & buffer . memory , range . clone ( ) ) } {
291- if !buffer . memory_properties . contains ( hal :: memory :: Properties :: COHERENT ) {
292- buffer . mapped_write_ranges . push ( range ) ;
290+ } ,
291+ BufferMapOperation :: Write ( range , .. ) => {
292+ if let Ok ( ptr ) = unsafe { raw . map_memory ( & buffer . memory , range . clone ( ) ) } {
293+ if !buffer . memory_properties . contains ( hal :: memory :: Properties :: COHERENT ) {
294+ buffer . mapped_write_ranges . push ( range . clone ( ) ) ;
295+ }
296+ ( BufferMapAsyncStatus :: Success , Some ( ptr ) )
297+ } else {
298+ ( BufferMapAsyncStatus :: Error , None )
293299 }
294- callback ( BufferMapAsyncStatus :: Success , ptr, userdata) ;
295- } else {
296- callback ( BufferMapAsyncStatus :: Error , std:: ptr:: null_mut ( ) , userdata) ;
297- }
298- } ,
299- _ => unreachable ! ( ) ,
300+ } ,
301+ }
302+ } ;
303+
304+ match operation. unwrap ( ) {
305+ BufferMapOperation :: Read ( _, callback, userdata) => callback ( result, ptr. unwrap_or ( std:: ptr:: null_mut ( ) ) , userdata) ,
306+ BufferMapOperation :: Write ( _, callback, userdata) => callback ( result, ptr. unwrap_or ( std:: ptr:: null_mut ( ) ) , userdata) ,
300307 } ;
301308 }
302309 }
@@ -1022,108 +1029,119 @@ pub extern "C" fn wgpu_queue_submit(
10221029 command_buffer_ptr : * const CommandBufferId ,
10231030 command_buffer_count : usize ,
10241031) {
1025- let mut device_guard = HUB . devices . write ( ) ;
1026- let device = & mut device_guard[ queue_id] ;
1027-
1028- let mut swap_chain_links = Vec :: new ( ) ;
10291032 let command_buffer_ids =
10301033 unsafe { slice:: from_raw_parts ( command_buffer_ptr, command_buffer_count) } ;
10311034
1032- let old_submit_index = device
1033- . life_guard
1034- . submission_index
1035- . fetch_add ( 1 , Ordering :: Relaxed ) ;
1036- let mut trackers = device. trackers . lock ( ) ;
1037-
1038- //TODO: if multiple command buffers are submitted, we can re-use the last
1039- // native command buffer of the previous chain instead of always creating
1040- // a temporary one, since the chains are not finished.
1041- {
1042- let mut command_buffer_guard = HUB . command_buffers . write ( ) ;
1043- let buffer_guard = HUB . buffers . read ( ) ;
1044- let texture_guard = HUB . textures . read ( ) ;
1045- let texture_view_guard = HUB . texture_views . read ( ) ;
1046-
1047- // finish all the command buffers first
1048- for & cmb_id in command_buffer_ids {
1049- let comb = & mut command_buffer_guard[ cmb_id] ;
1050- swap_chain_links. extend ( comb. swap_chain_links . drain ( ..) ) ;
1051- // update submission IDs
1052- comb. life_guard . submission_index
1053- . store ( old_submit_index, Ordering :: Release ) ;
1054- for id in comb. trackers . buffers . used ( ) {
1055- buffer_guard[ id] . life_guard . submission_index
1056- . store ( old_submit_index, Ordering :: Release ) ;
1057- }
1058- for id in comb. trackers . textures . used ( ) {
1059- texture_guard[ id] . life_guard . submission_index
1060- . store ( old_submit_index, Ordering :: Release ) ;
1061- }
1062- for id in comb. trackers . views . used ( ) {
1063- texture_view_guard[ id] . life_guard . submission_index
1035+ let ( old_submit_index, fence) = {
1036+ let mut device_guard = HUB . devices . write ( ) ;
1037+ let device = & mut device_guard[ queue_id] ;
1038+
1039+ let mut swap_chain_links = Vec :: new ( ) ;
1040+
1041+ let old_submit_index = device
1042+ . life_guard
1043+ . submission_index
1044+ . fetch_add ( 1 , Ordering :: Relaxed ) ;
1045+ let mut trackers = device. trackers . lock ( ) ;
1046+
1047+ //TODO: if multiple command buffers are submitted, we can re-use the last
1048+ // native command buffer of the previous chain instead of always creating
1049+ // a temporary one, since the chains are not finished.
1050+ {
1051+ let mut command_buffer_guard = HUB . command_buffers . write ( ) ;
1052+ let buffer_guard = HUB . buffers . read ( ) ;
1053+ let texture_guard = HUB . textures . read ( ) ;
1054+ let texture_view_guard = HUB . texture_views . read ( ) ;
1055+
1056+ // finish all the command buffers first
1057+ for & cmb_id in command_buffer_ids {
1058+ let comb = & mut command_buffer_guard[ cmb_id] ;
1059+ swap_chain_links. extend ( comb. swap_chain_links . drain ( ..) ) ;
1060+ // update submission IDs
1061+ comb. life_guard . submission_index
10641062 . store ( old_submit_index, Ordering :: Release ) ;
1065- }
1063+ for id in comb. trackers . buffers . used ( ) {
1064+ buffer_guard[ id] . life_guard . submission_index
1065+ . store ( old_submit_index, Ordering :: Release ) ;
1066+ }
1067+ for id in comb. trackers . textures . used ( ) {
1068+ texture_guard[ id] . life_guard . submission_index
1069+ . store ( old_submit_index, Ordering :: Release ) ;
1070+ }
1071+ for id in comb. trackers . views . used ( ) {
1072+ texture_view_guard[ id] . life_guard . submission_index
1073+ . store ( old_submit_index, Ordering :: Release ) ;
1074+ }
10661075
1067- // execute resource transitions
1068- let mut transit = device. com_allocator . extend ( comb) ;
1069- unsafe {
1070- transit. begin (
1071- hal:: command:: CommandBufferFlags :: ONE_TIME_SUBMIT ,
1072- hal:: command:: CommandBufferInheritanceInfo :: default ( ) ,
1076+ // execute resource transitions
1077+ let mut transit = device. com_allocator . extend ( comb) ;
1078+ unsafe {
1079+ transit. begin (
1080+ hal:: command:: CommandBufferFlags :: ONE_TIME_SUBMIT ,
1081+ hal:: command:: CommandBufferInheritanceInfo :: default ( ) ,
1082+ ) ;
1083+ }
1084+ command:: CommandBuffer :: insert_barriers (
1085+ & mut transit,
1086+ & mut * trackers,
1087+ & comb. trackers ,
1088+ Stitch :: Init ,
1089+ & * buffer_guard,
1090+ & * texture_guard,
10731091 ) ;
1092+ unsafe {
1093+ transit. finish ( ) ;
1094+ }
1095+ comb. raw . insert ( 0 , transit) ;
1096+ unsafe {
1097+ comb. raw . last_mut ( ) . unwrap ( ) . finish ( ) ;
1098+ }
10741099 }
1075- command:: CommandBuffer :: insert_barriers (
1076- & mut transit,
1077- & mut * trackers,
1078- & comb. trackers ,
1079- Stitch :: Init ,
1080- & * buffer_guard,
1081- & * texture_guard,
1082- ) ;
1083- unsafe {
1084- transit. finish ( ) ;
1085- }
1086- comb. raw . insert ( 0 , transit) ;
1100+ }
1101+
1102+ // now prepare the GPU submission
1103+ let fence = device. raw . create_fence ( false ) . unwrap ( ) ;
1104+ {
1105+ let command_buffer_guard = HUB . command_buffers . read ( ) ;
1106+ let surface_guard = HUB . surfaces . read ( ) ;
1107+
1108+ let wait_semaphores = swap_chain_links
1109+ . into_iter ( )
1110+ . flat_map ( |link| {
1111+ //TODO: check the epoch
1112+ surface_guard[ link. swap_chain_id ] . swap_chain
1113+ . as_ref ( )
1114+ . map ( |swap_chain| (
1115+ & swap_chain. frames [ link. image_index as usize ] . sem_available ,
1116+ hal:: pso:: PipelineStage :: COLOR_ATTACHMENT_OUTPUT ,
1117+ ) )
1118+ } ) ;
1119+
1120+ let submission =
1121+ hal:: queue:: Submission :: < _ , _ , & [ <back:: Backend as hal:: Backend >:: Semaphore ] > {
1122+ //TODO: may `OneShot` be enough?
1123+ command_buffers : command_buffer_ids
1124+ . iter ( )
1125+ . flat_map ( |& cmb_id| & command_buffer_guard[ cmb_id] . raw ) ,
1126+ wait_semaphores,
1127+ signal_semaphores : & [ ] , //TODO: signal `sem_present`?
1128+ } ;
1129+
10871130 unsafe {
1088- comb. raw . last_mut ( ) . unwrap ( ) . finish ( ) ;
1131+ device. queue_group . queues [ 0 ]
1132+ . as_raw_mut ( )
1133+ . submit ( submission, Some ( & fence) ) ;
10891134 }
10901135 }
1091- }
10921136
1093- // now prepare the GPU submission
1094- let fence = device. raw . create_fence ( false ) . unwrap ( ) ;
1095- {
1096- let command_buffer_guard = HUB . command_buffers . read ( ) ;
1097- let surface_guard = HUB . surfaces . read ( ) ;
1098-
1099- let wait_semaphores = swap_chain_links
1100- . into_iter ( )
1101- . flat_map ( |link| {
1102- //TODO: check the epoch
1103- surface_guard[ link. swap_chain_id ] . swap_chain
1104- . as_ref ( )
1105- . map ( |swap_chain| (
1106- & swap_chain. frames [ link. image_index as usize ] . sem_available ,
1107- hal:: pso:: PipelineStage :: COLOR_ATTACHMENT_OUTPUT ,
1108- ) )
1109- } ) ;
1137+ ( old_submit_index, fence)
1138+ } ;
11101139
1111- let submission =
1112- hal:: queue:: Submission :: < _ , _ , & [ <back:: Backend as hal:: Backend >:: Semaphore ] > {
1113- //TODO: may `OneShot` be enough?
1114- command_buffers : command_buffer_ids
1115- . iter ( )
1116- . flat_map ( |& cmb_id| & command_buffer_guard[ cmb_id] . raw ) ,
1117- wait_semaphores,
1118- signal_semaphores : & [ ] , //TODO: signal `sem_present`?
1119- } ;
1140+ // No need for write access to the device from here on out
1141+ let device_guard = HUB . devices . read ( ) ;
1142+ let device = & device_guard[ queue_id] ;
11201143
1121- unsafe {
1122- device. queue_group . queues [ 0 ]
1123- . as_raw_mut ( )
1124- . submit ( submission, Some ( & fence) ) ;
1125- }
1126- }
1144+ let mut trackers = device. trackers . lock ( ) ;
11271145
11281146 let last_done = {
11291147 let mut destroyed = device. destroyed . lock ( ) ;
0 commit comments