diff --git a/wgpu-native/src/track.rs b/wgpu-native/src/track.rs index cca3742c2f..4a8a88daa4 100644 --- a/wgpu-native/src/track.rs +++ b/wgpu-native/src/track.rs @@ -15,7 +15,7 @@ use hal::backend::FastHashMap; use std::{ borrow::Borrow, - collections::hash_map::Entry, + collections::hash_map::{Entry, Iter}, marker::PhantomData, mem, ops::{BitOr, Range}, @@ -112,6 +112,46 @@ pub enum Stitch { Last, } +//TODO: consider rewriting this without any iterators that have side effects. +pub struct ConsumeIterator<'a, I: TypedId, U: Copy + PartialEq> { + src: Iter<'a, Index, Track>, + dst: &'a mut FastHashMap>, + stitch: Stitch, + _marker: PhantomData, +} + +impl<'a, I: TypedId, U: Copy + PartialEq> Iterator for ConsumeIterator<'a, I, U> { + type Item = (I, Range); + fn next(&mut self) -> Option { + loop { + let (&index, new) = self.src.next()?; + match self.dst.entry(index) { + Entry::Vacant(e) => { + e.insert(new.clone()); + } + Entry::Occupied(mut e) => { + assert_eq!(e.get().epoch, new.epoch); + let old = mem::replace(&mut e.get_mut().last, new.last); + if old != new.init { + let state = match self.stitch { + Stitch::Init => new.init, + Stitch::Last => new.last, + }; + return Some((I::new(index, new.epoch), old .. state)) + } + } + } + } + } +} + +// Make sure to finish all side effects on drop +impl<'a, I: TypedId, U: Copy + PartialEq> Drop for ConsumeIterator<'a, I, U> { + fn drop(&mut self) { + self.for_each(drop) + } +} + pub struct TrackerSet { pub buffers: BufferTracker, pub textures: TextureTracker, @@ -227,29 +267,13 @@ impl + PartialEq> Tracker &'a mut self, other: &'a Self, stitch: Stitch, - ) -> impl 'a + Iterator)> { - other - .map - .iter() - .flat_map(move |(&index, new)| match self.map.entry(index) { - Entry::Vacant(e) => { - e.insert(new.clone()); - None - } - Entry::Occupied(mut e) => { - assert_eq!(e.get().epoch, new.epoch); - let old = mem::replace(&mut e.get_mut().last, new.last); - if old == new.init { - None - } else { - let state = match stitch { - Stitch::Init => new.init, - Stitch::Last => new.last, - }; - Some((I::new(index, new.epoch), old .. state)) - } - } - }) + ) -> ConsumeIterator<'a, I, U> { + ConsumeIterator { + src: other.map.iter(), + dst: &mut self.map, + stitch, + _marker: PhantomData, + } } /// Consume another tacker, adding it's transitions to `self`.