diff --git a/lock-analyzer/src/main.rs b/lock-analyzer/src/main.rs index 18f131ab8be..76e83dbe843 100644 --- a/lock-analyzer/src/main.rs +++ b/lock-analyzer/src/main.rs @@ -22,6 +22,10 @@ use std::{ use anyhow::{Context, Result}; +// When printing the rank graph, include the source locations where the acquisitions were +// observed. Setting this to `false` produces output that more closely matches `rank.rs`. +const PRINT_ACQUISITION_LOCATIONS: bool = false; + fn main() -> Result<()> { let mut ranks: BTreeMap = BTreeMap::default(); @@ -113,69 +117,108 @@ fn main() -> Result<()> { } } - for older_rank in ranks.values() { + // Perform a DFS traversal of the graph to generate a topological order for the ranks. + let mut order = Vec::with_capacity(ranks.len()); + let mut visited = 0; // mask of ranks visited by the DFS + let mut connected = 0; // mask of ranks that are connected to the graph + + fn visit( + order: &mut Vec, + visited: &mut u64, + connected: &mut u64, + ranks: &BTreeMap, + bit: u32, + ) { + if *visited & (1 << bit) != 0 { + return; + } + *visited |= 1 << bit; + + for &next_rank_bit in ranks[&bit].acquisitions.keys() { + *connected |= 1 << next_rank_bit; + visit(order, visited, connected, ranks, next_rank_bit); + } + + order.push(bit); + } + + for &bit in ranks.keys() { + visit(&mut order, &mut visited, &mut connected, &ranks, bit); + } + + order.reverse(); + + // Assemble the ranks into three groups: + // 1. Non-leaf ranks, in the topological order. + // 2. Leaf ranks that are connected to the graph, alphabetically. + // 3. Ranks that aren't connected to the graph at all, alphabetically. + let mut grouped_order = Vec::with_capacity(order.len()); + + grouped_order.extend(order.iter().filter(|bit| !ranks[bit].is_leaf())); + + grouped_order.extend({ + let mut tmp = order + .iter() + .copied() + .filter(|bit| ranks[bit].is_leaf() && connected & (1 << *bit) != 0) + .collect::>(); + tmp.sort_by_key(|bit| &ranks[bit].const_name); + tmp + }); + + grouped_order.extend({ + let mut tmp = order + .iter() + .copied() + .filter(|bit| ranks[bit].is_leaf() && connected & (1 << *bit) == 0) + .collect::>(); + tmp.sort_by_key(|bit| &ranks[bit].const_name); + tmp + }); + + // Finally, compute indexes so we can sort the followers of each rank in the same order + // as the ranks themselves. + let mut indices = vec![0; ranks.len()]; + for (i, &bit) in grouped_order.iter().enumerate() { + indices[bit as usize] = i; + } + + for bit in &grouped_order { + let older_rank = &ranks[bit]; if older_rank.is_leaf() { - // We'll print leaf locks separately, below. + println!( + " rank {} {:?} followed by {{ }};", + older_rank.const_name, older_rank.member_name + ); continue; } println!( " rank {} {:?} followed by {{", older_rank.const_name, older_rank.member_name ); - let mut acquired_any_leaf_locks = false; - let mut first_newer = true; - for (newer_rank, locations) in &older_rank.acquisitions { - // List acquisitions of leaf locks at the end. - if ranks[newer_rank].is_leaf() { - acquired_any_leaf_locks = true; - continue; - } - if !first_newer { - println!(); - } - for (older_location, newer_locations) in locations { - if newer_locations.len() == 1 { - for newer_loc in newer_locations { - println!(" // holding {older_location} while locking {newer_loc}"); - } - } else { - println!(" // holding {older_location} while locking:"); - for newer_loc in newer_locations { - println!(" // {newer_loc}"); + let mut acquisitions = older_rank.acquisitions.iter().collect::>(); + acquisitions.sort_by_key(|(&newer_rank, _)| indices[newer_rank as usize]); + for (newer_rank, locations) in acquisitions { + if PRINT_ACQUISITION_LOCATIONS { + for (older_location, newer_locations) in locations { + if newer_locations.len() == 1 { + for newer_loc in newer_locations { + println!( + " // holding {older_location} while locking {newer_loc}" + ); + } + } else { + println!(" // holding {older_location} while locking:"); + for newer_loc in newer_locations { + println!(" // {newer_loc}"); + } } } } println!(" {},", ranks[newer_rank].const_name); - first_newer = false; } - if acquired_any_leaf_locks { - // We checked that older_rank isn't a leaf lock, so we - // must have printed something above. - if !first_newer { - println!(); - } - println!(" // leaf lock acquisitions:"); - for newer_rank in older_rank.acquisitions.keys() { - if !ranks[newer_rank].is_leaf() { - continue; - } - println!(" {},", ranks[newer_rank].const_name); - } - } - println!(" }};"); - println!(); - } - - for older_rank in ranks.values() { - if !older_rank.is_leaf() { - continue; - } - - println!( - " rank {} {:?} followed by {{ }};", - older_rank.const_name, older_rank.member_name - ); + println!(" }}"); } Ok(()) diff --git a/wgpu-core/src/command/bundle.rs b/wgpu-core/src/command/bundle.rs index 4848427bea9..6e63f19a5ed 100644 --- a/wgpu-core/src/command/bundle.rs +++ b/wgpu-core/src/command/bundle.rs @@ -341,9 +341,9 @@ impl RenderBundleEncoder { .map_pass_err(scope)?; }; + let buffer_guard = hub.buffers.read(); let bind_group_guard = hub.bind_groups.read(); let pipeline_guard = hub.render_pipelines.read(); - let buffer_guard = hub.buffers.read(); let mut state = State { trackers: RenderBundleScope::new(), diff --git a/wgpu-core/src/command/mod.rs b/wgpu-core/src/command/mod.rs index fe5e0dd2c65..712fecdd8e9 100644 --- a/wgpu-core/src/command/mod.rs +++ b/wgpu-core/src/command/mod.rs @@ -1226,9 +1226,9 @@ impl CommandEncoder { self: &Arc, desc: &wgt::CommandBufferDescriptor