Make image Cache eviction strategy less aggressive in iced_wgpu
Instead of trimming unconditionally at the end of a frame, we now trim the cache only when there is a cache miss. This way, images that are not visible but still a part of the layout will stay cached. Eviction will only happen when the images are not a part of the UI for two consectuive frames.
This commit is contained in:
parent
fdcec03197
commit
493c36ac71
6 changed files with 41 additions and 5 deletions
|
|
@ -94,7 +94,7 @@ impl Atlas {
|
|||
entry
|
||||
};
|
||||
|
||||
log::info!("Allocated atlas entry: {entry:?}");
|
||||
log::debug!("Allocated atlas entry: {entry:?}");
|
||||
|
||||
// It is a webgpu requirement that:
|
||||
// BufferCopyView.layout.bytes_per_row % wgpu::COPY_BYTES_PER_ROW_ALIGNMENT == 0
|
||||
|
|
@ -147,13 +147,20 @@ impl Atlas {
|
|||
}
|
||||
}
|
||||
|
||||
log::info!("Current atlas: {self:?}");
|
||||
if log::log_enabled!(log::Level::Debug) {
|
||||
log::debug!(
|
||||
"Atlas layers: {} (busy: {}, allocations: {})",
|
||||
self.layer_count(),
|
||||
self.layers.iter().filter(|layer| !layer.is_empty()).count(),
|
||||
self.layers.iter().map(Layer::allocations).sum::<usize>(),
|
||||
);
|
||||
}
|
||||
|
||||
Some(entry)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, entry: &Entry) {
|
||||
log::info!("Removing atlas entry: {entry:?}");
|
||||
log::debug!("Removing atlas entry: {entry:?}");
|
||||
|
||||
match entry {
|
||||
Entry::Contiguous(allocation) => {
|
||||
|
|
@ -266,7 +273,7 @@ impl Atlas {
|
|||
}
|
||||
|
||||
fn deallocate(&mut self, allocation: &Allocation) {
|
||||
log::info!("Deallocating atlas: {allocation:?}");
|
||||
log::debug!("Deallocating atlas: {allocation:?}");
|
||||
|
||||
match allocation {
|
||||
Allocation::Full { layer } => {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,10 @@ impl Allocator {
|
|||
pub fn is_empty(&self) -> bool {
|
||||
self.allocations == 0
|
||||
}
|
||||
|
||||
pub fn allocations(&self) -> usize {
|
||||
self.allocations
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Region {
|
||||
|
|
|
|||
|
|
@ -11,4 +11,12 @@ impl Layer {
|
|||
pub fn is_empty(&self) -> bool {
|
||||
matches!(self, Layer::Empty)
|
||||
}
|
||||
|
||||
pub fn allocations(&self) -> usize {
|
||||
match self {
|
||||
Layer::Empty => 0,
|
||||
Layer::Busy(allocator) => allocator.allocations(),
|
||||
Layer::Full => 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -277,7 +277,7 @@ impl Pipeline {
|
|||
let texture_version = cache.layer_count();
|
||||
|
||||
if self.texture_version != texture_version {
|
||||
log::info!("Atlas has grown. Recreating bind group...");
|
||||
log::debug!("Atlas has grown. Recreating bind group...");
|
||||
|
||||
self.texture =
|
||||
cache.create_bind_group(device, &self.texture_layout);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ impl Memory {
|
|||
pub struct Cache {
|
||||
map: FxHashMap<u64, Memory>,
|
||||
hits: FxHashSet<u64>,
|
||||
should_trim: bool,
|
||||
}
|
||||
|
||||
impl Cache {
|
||||
|
|
@ -55,6 +56,8 @@ impl Cache {
|
|||
Err(_) => Memory::Invalid,
|
||||
};
|
||||
|
||||
self.should_trim = true;
|
||||
|
||||
self.insert(handle, memory);
|
||||
self.get(handle).unwrap()
|
||||
}
|
||||
|
|
@ -86,6 +89,11 @@ impl Cache {
|
|||
|
||||
/// Trim cache misses from cache
|
||||
pub fn trim(&mut self, atlas: &mut Atlas) {
|
||||
// Only trim if new entries have landed in the `Cache`
|
||||
if !self.should_trim {
|
||||
return;
|
||||
}
|
||||
|
||||
let hits = &self.hits;
|
||||
|
||||
self.map.retain(|k, memory| {
|
||||
|
|
@ -101,6 +109,7 @@ impl Cache {
|
|||
});
|
||||
|
||||
self.hits.clear();
|
||||
self.should_trim = false;
|
||||
}
|
||||
|
||||
fn get(&mut self, handle: &image::Handle) -> Option<&mut Memory> {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ pub struct Cache {
|
|||
rasterized: FxHashMap<(u64, u32, u32, ColorFilter), atlas::Entry>,
|
||||
svg_hits: FxHashSet<u64>,
|
||||
rasterized_hits: FxHashSet<(u64, u32, u32, ColorFilter)>,
|
||||
should_trim: bool,
|
||||
}
|
||||
|
||||
type ColorFilter = Option<[u8; 4]>;
|
||||
|
|
@ -76,6 +77,8 @@ impl Cache {
|
|||
}
|
||||
}
|
||||
|
||||
self.should_trim = true;
|
||||
|
||||
let _ = self.svgs.insert(handle.id(), svg);
|
||||
self.svgs.get(&handle.id()).unwrap()
|
||||
}
|
||||
|
|
@ -176,6 +179,10 @@ impl Cache {
|
|||
|
||||
/// Load svg and upload raster data
|
||||
pub fn trim(&mut self, atlas: &mut Atlas) {
|
||||
if !self.should_trim {
|
||||
return;
|
||||
}
|
||||
|
||||
let svg_hits = &self.svg_hits;
|
||||
let rasterized_hits = &self.rasterized_hits;
|
||||
|
||||
|
|
@ -191,6 +198,7 @@ impl Cache {
|
|||
});
|
||||
self.svg_hits.clear();
|
||||
self.rasterized_hits.clear();
|
||||
self.should_trim = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue