mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 1641751 - Part 1 - Remove some texture cache eviction paths r=Bert,kvark
This patch removes two of the existing paths for evicting textures. One is no longer useful, and the other is over-zealous, and causes frame stalls. When the shared texture cache made use of variable layer counts, the `maybe_reclaim_shared_memory` method would look at the space in free layers, and if large enough, would clear the entire cache and rely on it being rebuilt implicitly as new requests occur. However, since we no longer resize the number of slices, this doesn't serve a useful purpose (the texture cache already frees any empty texture cache units at the end of each frame). The other method applies a conservative, periodic GC that occurs if no other GCs have run for five seconds. However, this is a very aggressive eviction that often evicts most of the shared cache, and was being run whenever the size of the texture cache was > 16 MB. The effect of this is that if you pause scrolling for a few seconds, and then scroll again, most of the cache gets evicted. Instead, completely remove this concept, relying on empty texture cache pages being freed and memory pressure events, and general cache eviction during frames. Differential Revision: https://phabricator.services.mozilla.com/D77402
This commit is contained in:
parent
79fe28f0d6
commit
368ca0d02e
@ -38,10 +38,6 @@ const PICTURE_TILE_FORMAT: ImageFormat = ImageFormat::RGBA8;
|
||||
const TEXTURE_REGION_PIXELS: usize =
|
||||
(TEXTURE_REGION_DIMENSIONS as usize) * (TEXTURE_REGION_DIMENSIONS as usize);
|
||||
|
||||
// The minimum number of bytes that we must be able to reclaim in order
|
||||
// to justify clearing the entire shared cache in order to shrink it.
|
||||
const RECLAIM_THRESHOLD_BYTES: usize = 16 * 512 * 512 * 4;
|
||||
|
||||
/// Items in the texture cache can either be standalone textures,
|
||||
/// or a sub-rect inside the shared cache.
|
||||
#[derive(Debug)]
|
||||
@ -284,22 +280,6 @@ impl SharedTextures {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the cumulative number of GPU bytes consumed by all the shared textures.
|
||||
fn size_in_bytes(&self) -> usize {
|
||||
self.array_alpha8_linear.size_in_bytes() +
|
||||
self.array_alpha16_linear.size_in_bytes() +
|
||||
self.array_color8_linear.size_in_bytes() +
|
||||
self.array_color8_nearest.size_in_bytes()
|
||||
}
|
||||
|
||||
/// Returns the cumulative number of GPU bytes consumed by empty regions.
|
||||
fn reclaimable_region_bytes(&self) -> usize {
|
||||
self.array_alpha8_linear.reclaimable_region_bytes() +
|
||||
self.array_alpha16_linear.reclaimable_region_bytes() +
|
||||
self.array_color8_linear.reclaimable_region_bytes() +
|
||||
self.array_color8_nearest.reclaimable_region_bytes()
|
||||
}
|
||||
|
||||
/// Clears each texture in the set, with the given set of pending updates.
|
||||
fn clear(&mut self, updates: &mut TextureUpdateList) {
|
||||
self.array_alpha8_linear.clear(updates);
|
||||
@ -668,10 +648,6 @@ pub struct TextureCache {
|
||||
/// The current `FrameStamp`. Used for cache eviction policies.
|
||||
now: FrameStamp,
|
||||
|
||||
/// The time at which we first reached the byte threshold for reclaiming
|
||||
/// cache memory. `None if we haven't reached the threshold.
|
||||
reached_reclaim_threshold: Option<SystemTime>,
|
||||
|
||||
/// Maintains the list of all current items in the texture cache.
|
||||
entries: FreeList<CacheEntry, CacheEntryMarker>,
|
||||
|
||||
@ -747,7 +723,6 @@ impl TextureCache {
|
||||
&mut next_texture_id,
|
||||
&mut pending_updates,
|
||||
),
|
||||
reached_reclaim_threshold: None,
|
||||
entries: FreeList::new(),
|
||||
max_texture_size,
|
||||
max_texture_layers,
|
||||
@ -847,8 +822,7 @@ impl TextureCache {
|
||||
mem::replace(&mut self.doc_data, PerDocumentData::new()));
|
||||
}
|
||||
|
||||
pub fn prepare_for_frames(&mut self, time: SystemTime) {
|
||||
self.maybe_reclaim_shared_memory(time);
|
||||
pub fn prepare_for_frames(&mut self, _: SystemTime) {
|
||||
}
|
||||
|
||||
pub fn bookkeep_after_frames(&mut self) {
|
||||
@ -865,58 +839,6 @@ impl TextureCache {
|
||||
profile_scope!("begin_frame");
|
||||
self.now = stamp;
|
||||
self.set_doc_data();
|
||||
self.maybe_do_periodic_gc();
|
||||
}
|
||||
|
||||
fn maybe_reclaim_shared_memory(&mut self, time: SystemTime) {
|
||||
// If we've had a sufficient number of unused layers for a sufficiently
|
||||
// long time, just blow the whole cache away to shrink it.
|
||||
//
|
||||
// We could do this more intelligently with a resize+blit, but that would
|
||||
// add complexity for a rare case.
|
||||
//
|
||||
// This function must be called before the first begin_frame() for a group
|
||||
// of documents, otherwise documents could end up ignoring the
|
||||
// self.require_frame_build flag which is set if we end up calling
|
||||
// clear_shared.
|
||||
debug_assert!(!self.now.is_valid());
|
||||
if self.shared_textures.reclaimable_region_bytes() >= RECLAIM_THRESHOLD_BYTES {
|
||||
self.reached_reclaim_threshold.get_or_insert(time);
|
||||
} else {
|
||||
self.reached_reclaim_threshold = None;
|
||||
}
|
||||
if let Some(t) = self.reached_reclaim_threshold {
|
||||
let dur = time.duration_since(t).unwrap_or_default();
|
||||
if dur >= Duration::from_secs(5) {
|
||||
self.clear_shared();
|
||||
self.reached_reclaim_threshold = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Called at the beginning of each frame to periodically GC by expiring
|
||||
/// old shared entries. If necessary, the shared memory opened up as a
|
||||
/// result of expiring these entries will be reclaimed before the next
|
||||
/// group of document frames.
|
||||
fn maybe_do_periodic_gc(&mut self) {
|
||||
debug_assert!(self.now.is_valid());
|
||||
|
||||
// Normally the shared cache only gets GCed when we fail to allocate.
|
||||
// However, we also perform a periodic, conservative GC to ensure that
|
||||
// we recover unused memory in bounded time, rather than having it
|
||||
// depend on allocation patterns of subsequent content.
|
||||
let time_since_last_gc = self.now.time()
|
||||
.duration_since(self.doc_data.last_shared_cache_expiration.time())
|
||||
.unwrap_or_default();
|
||||
let do_periodic_gc = time_since_last_gc >= Duration::from_secs(5) &&
|
||||
self.shared_textures.size_in_bytes() >= RECLAIM_THRESHOLD_BYTES * 2;
|
||||
if do_periodic_gc {
|
||||
let threshold = EvictionThresholdBuilder::new(self.now)
|
||||
.max_frames(1)
|
||||
.max_time_s(10)
|
||||
.build();
|
||||
self.maybe_expire_old_shared_entries(threshold);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end_frame(&mut self, texture_cache_profile: &mut TextureCacheProfileCounters) {
|
||||
@ -1747,13 +1669,6 @@ impl TextureArray {
|
||||
num_regions * TEXTURE_REGION_PIXELS * bpp
|
||||
}
|
||||
|
||||
/// Returns the number of GPU bytes consumed by empty regions.
|
||||
fn reclaimable_region_bytes(&self) -> usize {
|
||||
let bpp = self.formats.internal.bytes_per_pixel() as usize;
|
||||
let empty_regions: usize = self.units.iter().map(|u| u.empty_regions).sum();
|
||||
empty_regions * TEXTURE_REGION_PIXELS * bpp
|
||||
}
|
||||
|
||||
fn clear(&mut self, updates: &mut TextureUpdateList) {
|
||||
for unit in self.units.drain(..) {
|
||||
updates.push_free(unit.texture_id);
|
||||
|
Loading…
Reference in New Issue
Block a user