diff --git a/crates/egui/src/load/texture_loader.rs b/crates/egui/src/load/texture_loader.rs index e75b0507060c..2ab4d8a57f1c 100644 --- a/crates/egui/src/load/texture_loader.rs +++ b/crates/egui/src/load/texture_loader.rs @@ -1,5 +1,3 @@ -use std::sync::atomic::{AtomicU64, Ordering::Relaxed}; - use emath::Vec2; use super::{ @@ -17,7 +15,7 @@ struct PrimaryKey { type Bucket = HashMap, Entry>; struct Entry { - last_used: AtomicU64, + last_used: u64, /// Size of the original SVG, if any, or the texel size of the image if not an SVG. source_size: Vec2, @@ -25,10 +23,15 @@ struct Entry { handle: TextureHandle, } +#[derive(Default)] +struct State { + pass_index: u64, + cache: HashMap, +} + #[derive(Default)] pub struct DefaultTextureLoader { - pass_index: AtomicU64, - cache: Mutex>, + state: Mutex, } impl TextureLoader for DefaultTextureLoader { @@ -55,7 +58,9 @@ impl TextureLoader for DefaultTextureLoader { None }; - let mut cache = self.cache.lock(); + let mut state = self.state.lock(); + let State { pass_index, cache } = &mut *state; + let bucket = cache .entry(PrimaryKey { uri: uri.to_owned(), @@ -63,10 +68,8 @@ impl TextureLoader for DefaultTextureLoader { }) .or_default(); - if let Some(texture) = bucket.get(&svg_size_hint) { - texture - .last_used - .store(self.pass_index.load(Relaxed), Relaxed); + if let Some(texture) = bucket.get_mut(&svg_size_hint) { + texture.last_used = *pass_index; let texture = SizedTexture::new(texture.handle.id(), texture.source_size); Ok(TexturePoll::Ready { texture }) } else { @@ -79,7 +82,7 @@ impl TextureLoader for DefaultTextureLoader { bucket.insert( svg_size_hint, Entry { - last_used: AtomicU64::new(self.pass_index.load(Relaxed)), + last_used: *pass_index, source_size, handle, }, @@ -104,33 +107,37 @@ impl TextureLoader for DefaultTextureLoader { fn forget(&self, uri: &str) { log::trace!("forget {uri:?}"); - self.cache.lock().retain(|key, _value| key.uri != uri); + self.state.lock().cache.retain(|key, _value| key.uri != uri); } fn forget_all(&self) { log::trace!("forget all"); - self.cache.lock().clear(); + self.state.lock().cache.clear(); } fn end_pass(&self, pass_index: u64) { - self.pass_index.store(pass_index, Relaxed); - let mut cache = self.cache.lock(); + let mut state = self.state.lock(); + state.pass_index = pass_index; + + let State { pass_index, cache } = &mut *state; + cache.retain(|_key, bucket| { if 2 <= bucket.len() { // There are multiple textures of the same URI (e.g. SVGs of different scales). // This could be because someone has an SVG in a resizable container, // and so we get a lot of different sizes of it. // This could wast VRAM, so we remove the ones that are not used in this frame. - bucket.retain(|_, texture| pass_index <= texture.last_used.load(Relaxed) + 1); + bucket.retain(|_, texture| *pass_index <= texture.last_used + 1); } !bucket.is_empty() }); } fn byte_size(&self) -> usize { - self.cache + self.state .lock() + .cache .values() .map(|bucket| { bucket diff --git a/crates/epaint/src/text/fonts.rs b/crates/epaint/src/text/fonts.rs index f1a6e63b46e1..fdfbfa61d31c 100644 --- a/crates/epaint/src/text/fonts.rs +++ b/crates/epaint/src/text/fonts.rs @@ -3,7 +3,7 @@ use std::{ collections::BTreeMap, sync::{ Arc, - atomic::{AtomicU64, Ordering}, + atomic::{AtomicUsize, Ordering}, }, }; @@ -439,7 +439,7 @@ impl FontFaceKey { pub const INVALID: Self = Self(0); fn new() -> Self { - static KEY_COUNTER: AtomicU64 = AtomicU64::new(1); + static KEY_COUNTER: AtomicUsize = AtomicUsize::new(1); Self(crate::util::hash( KEY_COUNTER.fetch_add(1, Ordering::Relaxed), ))