diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index ff3d640321..e3f70b68d2 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -609,7 +609,6 @@ impl Global { let (compute_pipe_guard, mut token) = hub.compute_pipelines.read(&mut token); let (render_pipe_guard, mut token) = hub.render_pipelines.read(&mut token); let (mut buffer_guard, mut token) = hub.buffers.write(&mut token); - // This could be made immutable. It's only mutated for the `has_work` flag. let (mut texture_guard, mut token) = hub.textures.write(&mut token); let (texture_view_guard, mut token) = hub.texture_views.read(&mut token); let (sampler_guard, mut token) = hub.samplers.read(&mut token); @@ -684,34 +683,15 @@ impl Global { *has_work = true; let ref_count = cmdbuf.trackers.textures.get_ref_count(id); //TODO: better error handling here? - { - // first, register it in the device tracker with uninitialized, - // if it wasn't used before. - let mut ts = track::TextureState::default(); - let _ = ts.change( - id, - texture.full_range.clone(), - hal::TextureUses::UNINITIALIZED, - None, - ); - let _ = trackers.textures.init( - id, - ref_count.clone(), - ts.clone(), - ); - } - { - // then, register it in the temporary tracker. - let mut ts = track::TextureState::default(); - let _ = ts.change( - id, - texture.full_range.clone(), - hal::TextureUses::empty(), - None, - ); - let _ = - used_surface_textures.init(id, ref_count.clone(), ts); - } + // register it in the temporary tracker. + let mut ts = track::TextureState::default(); + let _ = ts.change( + id, + texture.full_range.clone(), + hal::TextureUses::empty(), //present + None, + ); + let _ = used_surface_textures.init(id, ref_count.clone(), ts); } } if !texture.life_guard.use_at(submit_index) { @@ -840,6 +820,63 @@ impl Global { ref mut fence, .. } = *device; + + { + //TODO: these blocks have a few organizational issues and should be refactored + // (1) it's similar to the code we have per-command-buffer (at the begin and end) + // Maybe we an merge some? + // (2) it's doing the extra locking unconditionally + // Maybe we can only do so if any surfaces are being written to? + + let (_, mut token) = hub.buffers.read(&mut token); // skip token + let (mut texture_guard, _) = hub.textures.write(&mut token); + + for &id in pending_writes.dst_textures.iter() { + let texture = texture_guard.get_mut(id).unwrap(); + match texture.inner { + TextureInner::Native { raw: None } => { + return Err(QueueSubmitError::DestroyedTexture(id)); + } + TextureInner::Native { raw: Some(_) } => {} + TextureInner::Surface { + ref mut has_work, .. + } => { + use track::ResourceState as _; + + *has_work = true; + let ref_count = texture.life_guard.add_ref(); + //TODO: better error handling here? + // register it in the temporary tracker. + let mut ts = track::TextureState::default(); + let _ = ts.change( + id::Valid(id), + texture.full_range.clone(), + hal::TextureUses::empty(), //present + None, + ); + let _ = used_surface_textures.init(id::Valid(id), ref_count, ts); + } + } + } + + if !used_surface_textures.is_empty() { + let mut trackers = device.trackers.lock(); + let texture_barriers = trackers + .textures + .merge_replace(&used_surface_textures) + .map(|pending| { + let tex = &texture_guard[pending.id]; + pending.into_hal(tex) + }); + unsafe { + pending_writes + .command_encoder + .transition_textures(texture_barriers); + }; + used_surface_textures.clear(); + } + } + let refs = pending_writes .pre_submit() .into_iter() diff --git a/wgpu-core/src/present.rs b/wgpu-core/src/present.rs index f9a9a09bd0..e8c28c6e87 100644 --- a/wgpu-core/src/present.rs +++ b/wgpu-core/src/present.rs @@ -19,9 +19,7 @@ use crate::{ hub::{Global, GlobalIdentityHandlerFactory, HalApi, Input, Token}, id::{DeviceId, SurfaceId, TextureId, Valid}, init_tracker::TextureInitTracker, - resource, - track::TextureSelector, - LifeGuard, Stored, + resource, track, LifeGuard, Stored, }; use hal::{Queue as _, Surface as _}; @@ -174,7 +172,7 @@ impl Global { | wgt::TextureFormatFeatureFlags::MULTISAMPLE_RESOLVE, }, initialization_status: TextureInitTracker::new(1, 1), - full_range: TextureSelector { + full_range: track::TextureSelector { layers: 0..1, levels: 0..1, }, @@ -188,7 +186,22 @@ impl Global { let ref_count = texture.life_guard.add_ref(); let id = fid.assign(texture, &mut token); - //suf.acquired_texture = Some(suf_texture); + { + use track::ResourceState as _; + // register it in the device tracker as uninitialized + let mut trackers = device.trackers.lock(); + let mut ts = track::TextureState::default(); + let _ = ts.change( + id, + track::TextureSelector { + layers: 0..1, + levels: 0..1, + }, + hal::TextureUses::UNINITIALIZED, + None, + ); + let _ = trackers.textures.init(id, ref_count.clone(), ts); + } if present.acquired_texture.is_some() { return Err(SurfaceError::AlreadyAcquired);