Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 23 additions & 21 deletions wgpu-core/src/command/memory_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,28 +268,30 @@ impl BakedCommands {

let mut ranges: Vec<TextureInitRange> = Vec::new();
for texture_use in self.texture_memory_actions.drain_init_actions() {
let mut initialization_status = texture_use.texture.initialization_status.write();
let use_range = texture_use.range;
let affected_mip_trackers = initialization_status
.mips
.iter_mut()
.enumerate()
.skip(use_range.mip_range.start as usize)
.take((use_range.mip_range.end - use_range.mip_range.start) as usize);

match texture_use.kind {
MemoryInitKind::ImplicitlyInitialized => {
for (_, mip_tracker) in affected_mip_trackers {
mip_tracker.drain(use_range.layer_range.clone());
{
let mut initialization_status = texture_use.texture.initialization_status.write();
let use_range = texture_use.range;
let affected_mip_trackers = initialization_status
.mips
.iter_mut()
.enumerate()
.skip(use_range.mip_range.start as usize)
.take((use_range.mip_range.end - use_range.mip_range.start) as usize);

match texture_use.kind {
MemoryInitKind::ImplicitlyInitialized => {
for (_, mip_tracker) in affected_mip_trackers {
mip_tracker.drain(use_range.layer_range.clone());
}
}
}
MemoryInitKind::NeedsInitializedMemory => {
for (mip_level, mip_tracker) in affected_mip_trackers {
for layer_range in mip_tracker.drain(use_range.layer_range.clone()) {
ranges.push(TextureInitRange {
mip_range: (mip_level as u32)..(mip_level as u32 + 1),
layer_range,
});
MemoryInitKind::NeedsInitializedMemory => {
for (mip_level, mip_tracker) in affected_mip_trackers {
for layer_range in mip_tracker.drain(use_range.layer_range.clone()) {
ranges.push(TextureInitRange {
mip_range: (mip_level as u32)..(mip_level as u32 + 1),
layer_range,
});
}
}
}
}
Expand Down
12 changes: 10 additions & 2 deletions wgpu-core/src/device/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1903,6 +1903,9 @@ impl Global {
///
/// Return `all_queue_empty` indicating whether there are more queue
/// submissions still in flight.
///
/// Upon entry, collects the set of devices to poll. Will not poll new
/// devices created while polling the initial set.
fn poll_all_devices_of_api(
&self,
force_wait: bool,
Expand All @@ -1913,9 +1916,14 @@ impl Global {
let hub = &self.hub;
let mut all_queue_empty = true;
{
let device_guard = hub.devices.read();
let devices = hub
.devices
.read()
.iter()
.map(|(_id, device)| device.clone())
.collect::<Vec<_>>();

for (_id, device) in device_guard.iter() {
for device in devices {
let poll_type = if force_wait {
// TODO(#8286): Should expose timeout to poll_all.
wgt::PollType::wait_indefinitely()
Expand Down
138 changes: 77 additions & 61 deletions wgpu-core/src/device/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,8 +582,9 @@ impl WebGpuError for QueueSubmitError {
/// [`submit`]: `PendingSubmission::submit`
pub(crate) struct PendingSubmission<'a> {
queue: &'a Queue,
snatch_guard: SnatchGuard<'a>,
// The lock ordering checker cares about the drop order for these guards.
command_index_guard: RwLockWriteGuard<'a, CommandIndices>,
snatch_guard: SnatchGuard<'a>,
// Command buffers to be executed, along with trackers for the resources they use.
pub executions: Vec<EncoderInFlight>,
// Surface textures referenced by command buffers in this submission. These need to be
Expand Down Expand Up @@ -659,12 +660,8 @@ impl Queue {
buffer_offset,
);

drop(snatch_guard);

pending_writes.consume(staging_buffer);

drop(pending_writes);

result
}

Expand Down Expand Up @@ -916,35 +913,44 @@ impl Queue {
} else {
destination.origin.z..destination.origin.z + size.depth_or_array_layers
};
let mut dst_initialization_status = dst.initialization_status.write();
if dst_initialization_status.mips[destination.mip_level as usize]
.check(init_layer_range.clone())
.is_some()
{
if has_copy_partial_init_tracker_coverage(size, &destination, &dst.desc) {
for layer_range in dst_initialization_status.mips[destination.mip_level as usize]
.drain(init_layer_range)
.collect::<Vec<core::ops::Range<u32>>>()
{
let mut trackers = self.device.trackers.lock();
crate::command::clear_texture(
&dst,
TextureInitRange {
mip_range: destination.mip_level..(destination.mip_level + 1),
layer_range,
},
encoder,
&mut trackers.textures,
&self.device.alignments,
self.device.zero_buffer.as_ref(),
&snatch_guard,
self.device.instance_flags,
let layer_ranges_to_clear = {
let mut dst_initialization_status = dst.initialization_status.write();
if dst_initialization_status.mips[destination.mip_level as usize]
.check(init_layer_range.clone())
.is_some()
{
if has_copy_partial_init_tracker_coverage(size, &destination, &dst.desc) {
Some(
dst_initialization_status.mips[destination.mip_level as usize]
.drain(init_layer_range)
.collect::<Vec<core::ops::Range<u32>>>(),
)
.map_err(QueueWriteError::from)?;
} else {
dst_initialization_status.mips[destination.mip_level as usize]
.drain(init_layer_range);
None
}
} else {
dst_initialization_status.mips[destination.mip_level as usize]
.drain(init_layer_range);
None
}
};
if let Some(layer_ranges) = layer_ranges_to_clear {
let mut trackers = self.device.trackers.lock();
for layer_range in layer_ranges {
crate::command::clear_texture(
&dst,
TextureInitRange {
mip_range: destination.mip_level..(destination.mip_level + 1),
layer_range,
},
encoder,
&mut trackers.textures,
&self.device.alignments,
self.device.zero_buffer.as_ref(),
&snatch_guard,
self.device.instance_flags,
)
.map_err(QueueWriteError::from)?;
}
}

Expand Down Expand Up @@ -1157,6 +1163,10 @@ impl Queue {

let (selector, dst_base) = extract_texture_selector(&destination, &size, &dst)?;

let snatch_guard = self.device.snatchable_lock.read();

let dst_raw = dst.try_raw(&snatch_guard)?;

// This must happen after parameter validation (so that errors are reported
// as required by the spec), but before any side effects.
if size.width == 0 || size.height == 0 || size.depth_or_array_layers == 0 {
Expand All @@ -1178,41 +1188,47 @@ impl Queue {
} else {
destination.origin.z..destination.origin.z + size.depth_or_array_layers
};
let mut dst_initialization_status = dst.initialization_status.write();
if dst_initialization_status.mips[destination.mip_level as usize]
.check(init_layer_range.clone())
.is_some()
{
if has_copy_partial_init_tracker_coverage(&size, &destination, &dst.desc) {
for layer_range in dst_initialization_status.mips[destination.mip_level as usize]
.drain(init_layer_range)
.collect::<Vec<core::ops::Range<u32>>>()
{
let mut trackers = self.device.trackers.lock();
crate::command::clear_texture(
&dst,
TextureInitRange {
mip_range: destination.mip_level..(destination.mip_level + 1),
layer_range,
},
encoder,
&mut trackers.textures,
&self.device.alignments,
self.device.zero_buffer.as_ref(),
&self.device.snatchable_lock.read(),
self.device.instance_flags,
let layer_ranges_to_clear = {
let mut dst_initialization_status = dst.initialization_status.write();
if dst_initialization_status.mips[destination.mip_level as usize]
.check(init_layer_range.clone())
.is_some()
{
if has_copy_partial_init_tracker_coverage(&size, &destination, &dst.desc) {
Some(
dst_initialization_status.mips[destination.mip_level as usize]
.drain(init_layer_range)
.collect::<Vec<core::ops::Range<u32>>>(),
)
.map_err(QueueWriteError::from)?;
} else {
dst_initialization_status.mips[destination.mip_level as usize]
.drain(init_layer_range);
None
}
} else {
dst_initialization_status.mips[destination.mip_level as usize]
.drain(init_layer_range);
None
}
};
if let Some(layer_ranges) = layer_ranges_to_clear {
let mut trackers = self.device.trackers.lock();
for layer_range in layer_ranges {
crate::command::clear_texture(
&dst,
TextureInitRange {
mip_range: destination.mip_level..(destination.mip_level + 1),
layer_range,
},
encoder,
&mut trackers.textures,
&self.device.alignments,
self.device.zero_buffer.as_ref(),
&snatch_guard,
self.device.instance_flags,
)
.map_err(QueueWriteError::from)?;
}
}

let snatch_guard = self.device.snatchable_lock.read();
let dst_raw = dst.try_raw(&snatch_guard)?;

let regions = hal::TextureCopy {
src_base: hal::TextureCopyBase {
mip_level: 0,
Expand Down Expand Up @@ -1586,8 +1602,8 @@ impl Queue {

let submission = PendingSubmission {
queue: self,
snatch_guard,
command_index_guard,
snatch_guard,
executions: Vec::new(),
surface_textures: FastHashMap::default(),
index,
Expand Down
25 changes: 16 additions & 9 deletions wgpu-core/src/device/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5377,17 +5377,24 @@ impl Device {
// initiate movement into those buckets, and it can do that by calling
// "destroy" on all the resources we know about.

// During these iterations, we discard all errors. We don't care!
let trackers = self.trackers.lock();
for buffer in trackers.buffers.used_resources() {
if let Some(buffer) = Weak::upgrade(buffer) {
buffer.destroy();
}
let buffers = trackers
.buffers
.used_resources()
.flat_map(Weak::upgrade)
.collect::<Vec<_>>();
let textures = trackers
.textures
.used_resources()
.flat_map(Weak::upgrade)
.collect::<Vec<_>>();
drop(trackers);

for buffer in buffers {
buffer.destroy();
}
for texture in trackers.textures.used_resources() {
if let Some(texture) = Weak::upgrade(texture) {
texture.destroy();
}
for texture in textures {
texture.destroy();
}
}

Expand Down