Introduce Mode for text::Cache and trim only when switching modes

This commit is contained in:
Héctor Ramón Jiménez 2023-06-29 17:54:54 +02:00
parent 0cc85c7820
commit 98febd9a42
No known key found for this signature in database
GPG key ID: 140CC052C94F138E

View file

@ -80,6 +80,11 @@ impl Pipeline {
let renderer = &mut self.renderers[self.prepare_layer]; let renderer = &mut self.renderers[self.prepare_layer];
let cache = self.cache.get_mut(); let cache = self.cache.get_mut();
if self.prepare_layer == 0 {
let _ = cache.switch(Mode::Drawing);
cache.trim();
}
let keys: Vec<_> = sections let keys: Vec<_> = sections
.iter() .iter()
.map(|section| { .map(|section| {
@ -224,7 +229,6 @@ impl Pipeline {
pub fn end_frame(&mut self) { pub fn end_frame(&mut self) {
self.atlas.trim(); self.atlas.trim();
self.cache.get_mut().trim();
self.prepare_layer = 0; self.prepare_layer = 0;
} }
@ -238,11 +242,15 @@ impl Pipeline {
bounds: Size, bounds: Size,
shaping: Shaping, shaping: Shaping,
) -> Size { ) -> Size {
let mut measurement_cache = self.cache.borrow_mut(); let mut cache = self.cache.borrow_mut();
let line_height = f32::from(line_height.to_absolute(Pixels(size))); let line_height = f32::from(line_height.to_absolute(Pixels(size)));
let (_, entry) = measurement_cache.allocate( if cache.switch(Mode::Measuring) {
cache.trim();
}
let (_, entry) = cache.allocate(
&mut self.font_system.borrow_mut(), &mut self.font_system.borrow_mut(),
Key { Key {
content, content,
@ -268,11 +276,15 @@ impl Pipeline {
point: Point, point: Point,
_nearest_only: bool, _nearest_only: bool,
) -> Option<Hit> { ) -> Option<Hit> {
let mut measurement_cache = self.cache.borrow_mut(); let mut cache = self.cache.borrow_mut();
let line_height = f32::from(line_height.to_absolute(Pixels(size))); let line_height = f32::from(line_height.to_absolute(Pixels(size)));
let (_, entry) = measurement_cache.allocate( if cache.switch(Mode::Measuring) {
cache.trim();
}
let (_, entry) = cache.allocate(
&mut self.font_system.borrow_mut(), &mut self.font_system.borrow_mut(),
Key { Key {
content, content,
@ -348,9 +360,11 @@ fn to_shaping(shaping: Shaping) -> glyphon::Shaping {
struct Cache { struct Cache {
entries: FxHashMap<KeyHash, Entry>, entries: FxHashMap<KeyHash, Entry>,
measurements: FxHashMap<KeyHash, KeyHash>, aliases: FxHashMap<KeyHash, KeyHash>,
recently_used: FxHashSet<KeyHash>, recently_measured: FxHashSet<KeyHash>,
recently_drawn: FxHashSet<KeyHash>,
hasher: HashBuilder, hasher: HashBuilder,
mode: Mode,
} }
struct Entry { struct Entry {
@ -358,6 +372,12 @@ struct Entry {
bounds: Size, bounds: Size,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Mode {
Measuring,
Drawing,
}
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
type HashBuilder = twox_hash::RandomXxHashBuilder64; type HashBuilder = twox_hash::RandomXxHashBuilder64;
@ -368,9 +388,11 @@ impl Cache {
fn new() -> Self { fn new() -> Self {
Self { Self {
entries: FxHashMap::default(), entries: FxHashMap::default(),
measurements: FxHashMap::default(), aliases: FxHashMap::default(),
recently_used: FxHashSet::default(), recently_measured: FxHashSet::default(),
recently_drawn: FxHashSet::default(),
hasher: HashBuilder::default(), hasher: HashBuilder::default(),
mode: Mode::Measuring,
} }
} }
@ -378,6 +400,14 @@ impl Cache {
self.entries.get(key) self.entries.get(key)
} }
fn switch(&mut self, mode: Mode) -> bool {
let has_changed = self.mode != mode;
self.mode = mode;
has_changed
}
fn allocate( fn allocate(
&mut self, &mut self,
font_system: &mut glyphon::FontSystem, font_system: &mut glyphon::FontSystem,
@ -385,8 +415,13 @@ impl Cache {
) -> (KeyHash, &mut Entry) { ) -> (KeyHash, &mut Entry) {
let hash = key.hash(self.hasher.build_hasher()); let hash = key.hash(self.hasher.build_hasher());
if let Some(hash) = self.measurements.get(&hash) { let recently_used = match self.mode {
let _ = self.recently_used.insert(*hash); Mode::Measuring => &mut self.recently_measured,
Mode::Drawing => &mut self.recently_drawn,
};
if let Some(hash) = self.aliases.get(&hash) {
let _ = recently_used.insert(*hash);
return (*hash, self.entries.get_mut(hash).unwrap()); return (*hash, self.entries.get_mut(hash).unwrap());
} }
@ -421,7 +456,7 @@ impl Cache {
}, },
] { ] {
if key.bounds != bounds { if key.bounds != bounds {
let _ = self.measurements.insert( let _ = self.aliases.insert(
Key { bounds, ..key }.hash(self.hasher.build_hasher()), Key { bounds, ..key }.hash(self.hasher.build_hasher()),
hash, hash,
); );
@ -429,18 +464,29 @@ impl Cache {
} }
} }
let _ = self.recently_used.insert(hash); let _ = recently_used.insert(hash);
(hash, self.entries.get_mut(&hash).unwrap()) (hash, self.entries.get_mut(&hash).unwrap())
} }
fn trim(&mut self) { fn trim(&mut self) {
self.entries self.entries.retain(|key, _| {
.retain(|key, _| self.recently_used.contains(key)); self.recently_measured.contains(key)
self.measurements || self.recently_drawn.contains(key)
.retain(|_, value| self.recently_used.contains(value)); });
self.aliases.retain(|_, value| {
self.recently_measured.contains(value)
|| self.recently_drawn.contains(value)
});
self.recently_used.clear(); match self.mode {
Mode::Measuring => {
self.recently_measured.clear();
}
Mode::Drawing => {
self.recently_drawn.clear();
}
}
} }
} }