Fix cache trimming loop in iced_wgpu::text
This commit is contained in:
parent
c51b85e7ab
commit
b276a603a1
2 changed files with 52 additions and 9 deletions
|
|
@ -15,7 +15,7 @@ impl<T> Cache<T> {
|
||||||
/// Creates a new empty [`Cache`].
|
/// Creates a new empty [`Cache`].
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Cache {
|
Cache {
|
||||||
group: Group::unique(),
|
group: Group::singleton(),
|
||||||
state: RefCell::new(State::Empty { previous: None }),
|
state: RefCell::new(State::Empty { previous: None }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -27,6 +27,11 @@ impl<T> Cache<T> {
|
||||||
/// You should generally group caches that are likely to change
|
/// You should generally group caches that are likely to change
|
||||||
/// together.
|
/// together.
|
||||||
pub fn with_group(group: Group) -> Self {
|
pub fn with_group(group: Group) -> Self {
|
||||||
|
assert!(
|
||||||
|
!group.is_singleton(),
|
||||||
|
"The group {group:?} cannot be shared!"
|
||||||
|
);
|
||||||
|
|
||||||
Cache {
|
Cache {
|
||||||
group,
|
group,
|
||||||
state: RefCell::new(State::Empty { previous: None }),
|
state: RefCell::new(State::Empty { previous: None }),
|
||||||
|
|
@ -75,14 +80,40 @@ impl<T> Cache<T> {
|
||||||
/// A cache group can be used to implement certain performance
|
/// A cache group can be used to implement certain performance
|
||||||
/// optimizations during rendering, like batching or sharing atlases.
|
/// optimizations during rendering, like batching or sharing atlases.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct Group(u64);
|
pub struct Group {
|
||||||
|
id: u64,
|
||||||
|
is_singleton: bool,
|
||||||
|
}
|
||||||
|
|
||||||
impl Group {
|
impl Group {
|
||||||
/// Generates a new unique cache [`Group`].
|
/// Generates a new unique cache [`Group`].
|
||||||
pub fn unique() -> Self {
|
pub fn unique() -> Self {
|
||||||
static NEXT: AtomicU64 = AtomicU64::new(0);
|
static NEXT: AtomicU64 = AtomicU64::new(0);
|
||||||
|
|
||||||
Self(NEXT.fetch_add(1, atomic::Ordering::Relaxed))
|
Self {
|
||||||
|
id: NEXT.fetch_add(1, atomic::Ordering::Relaxed),
|
||||||
|
is_singleton: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the [`Group`] can only ever have a
|
||||||
|
/// single [`Cache`] in it.
|
||||||
|
///
|
||||||
|
/// This is the default kind of [`Group`] assigned when using
|
||||||
|
/// [`Cache::new`].
|
||||||
|
///
|
||||||
|
/// Knowing that a [`Group`] will never be shared may be
|
||||||
|
/// useful for rendering backends to perform additional
|
||||||
|
/// optimizations.
|
||||||
|
pub fn is_singleton(self) -> bool {
|
||||||
|
self.is_singleton
|
||||||
|
}
|
||||||
|
|
||||||
|
fn singleton() -> Self {
|
||||||
|
Self {
|
||||||
|
is_singleton: true,
|
||||||
|
..Self::unique()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -157,13 +157,16 @@ impl Storage {
|
||||||
target_size,
|
target_size,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Only trim if glyphs have changed
|
||||||
|
group.should_trim =
|
||||||
|
group.should_trim || upload.version != cache.version;
|
||||||
|
|
||||||
upload.text = Rc::downgrade(&cache.text);
|
upload.text = Rc::downgrade(&cache.text);
|
||||||
upload.version = cache.version;
|
upload.version = cache.version;
|
||||||
upload.group_version = group.version;
|
upload.group_version = group.version;
|
||||||
upload.transformation = new_transformation;
|
upload.transformation = new_transformation;
|
||||||
|
|
||||||
upload.buffer_cache.trim();
|
upload.buffer_cache.trim();
|
||||||
group.should_trim = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hash_map::Entry::Vacant(entry) => {
|
hash_map::Entry::Vacant(entry) => {
|
||||||
|
|
@ -213,19 +216,28 @@ impl Storage {
|
||||||
.retain(|_id, upload| upload.text.strong_count() > 0);
|
.retain(|_id, upload| upload.text.strong_count() > 0);
|
||||||
|
|
||||||
self.groups.retain(|id, group| {
|
self.groups.retain(|id, group| {
|
||||||
if Rc::weak_count(&group.handle) == 0 {
|
let active_uploads = Rc::weak_count(&group.handle);
|
||||||
|
|
||||||
|
if active_uploads == 0 {
|
||||||
log::debug!("Dropping text atlas: {id:?}");
|
log::debug!("Dropping text atlas: {id:?}");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if group.should_trim {
|
if id.is_singleton() || group.should_trim {
|
||||||
log::debug!("Trimming text atlas: {id:?}");
|
log::debug!(
|
||||||
|
"Trimming text atlas: {id:?} (uploads: {active_uploads})"
|
||||||
|
);
|
||||||
|
|
||||||
group.atlas.trim();
|
group.atlas.trim();
|
||||||
|
|
||||||
group.version += 1;
|
|
||||||
group.should_trim = false;
|
group.should_trim = false;
|
||||||
|
|
||||||
|
// We only need to worry about glyph fighting
|
||||||
|
// when the atlas may be shared by multiple
|
||||||
|
// uploads.
|
||||||
|
if !id.is_singleton() {
|
||||||
|
group.version += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue