Bug 1548131 - WR reset texture allocation r=gw

Introduce a new texture allocation operation "reset", which acts like a "realloc" but without the contents preserved.
Use it for the picture texture cache.

Differential Revision: https://phabricator.services.mozilla.com/D29539

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Dzmitry Malyshau 2019-05-01 22:43:16 +00:00
Родитель 512461990a
Коммит 9512939607
5 изменённых файлов: 81 добавлений и 26 удалений

Просмотреть файл

@ -146,6 +146,8 @@ pub enum TextureCacheAllocationKind {
/// will be deallocated and its contents blitted over. The new size must
/// be greater than the old size.
Realloc(TextureCacheAllocInfo),
/// Reallocates the texture without preserving its contents.
Reset(TextureCacheAllocInfo),
/// Frees the texture and the corresponding cache ID.
Free,
}
@ -242,10 +244,10 @@ impl TextureUpdateList {
match cur.kind {
TextureCacheAllocationKind::Alloc(ref mut i) => *i = info,
TextureCacheAllocationKind::Realloc(ref mut i) => *i = info,
TextureCacheAllocationKind::Reset(ref mut i) => *i = info,
TextureCacheAllocationKind::Free => panic!("Reallocating freed texture"),
}
return;
return
}
self.allocations.push(TextureCacheAllocation {
@ -254,6 +256,31 @@ impl TextureUpdateList {
});
}
/// Pushes a reallocation operation onto the list, potentially coalescing
/// with previous operations.
pub fn push_reset(&mut self, id: CacheTextureId, info: TextureCacheAllocInfo) {
self.debug_assert_coalesced(id);
// Coallesce this realloc into a previous alloc or realloc, if available.
if let Some(cur) = self.allocations.iter_mut().find(|x| x.id == id) {
match cur.kind {
TextureCacheAllocationKind::Alloc(ref mut i) => *i = info,
TextureCacheAllocationKind::Reset(ref mut i) => *i = info,
TextureCacheAllocationKind::Free => panic!("Resetting freed texture"),
TextureCacheAllocationKind::Realloc(_) => {
// Reset takes precedence over realloc
cur.kind = TextureCacheAllocationKind::Reset(info);
}
}
return
}
self.allocations.push(TextureCacheAllocation {
id,
kind: TextureCacheAllocationKind::Reset(info),
});
}
/// Pushes a free operation onto the list, potentially coalescing with
/// previous operations.
pub fn push_free(&mut self, id: CacheTextureId) {
@ -269,7 +296,9 @@ impl TextureUpdateList {
match removed_kind {
Some(TextureCacheAllocationKind::Alloc(..)) => { /* no-op! */ },
Some(TextureCacheAllocationKind::Free) => panic!("Double free"),
Some(TextureCacheAllocationKind::Realloc(..)) | None => {
Some(TextureCacheAllocationKind::Realloc(..)) |
Some(TextureCacheAllocationKind::Reset(..)) |
None => {
self.allocations.push(TextureCacheAllocation {
id,
kind: TextureCacheAllocationKind::Free,

Просмотреть файл

@ -3300,10 +3300,10 @@ impl Renderer {
upload_time.profile(|| {
for update_list in pending_texture_updates.drain(..) {
for allocation in update_list.allocations {
let is_realloc = matches!(allocation.kind, TextureCacheAllocationKind::Realloc(..));
match allocation.kind {
TextureCacheAllocationKind::Alloc(info) |
TextureCacheAllocationKind::Realloc(info) => {
let old = match allocation.kind {
TextureCacheAllocationKind::Alloc(ref info) |
TextureCacheAllocationKind::Realloc(ref info) |
TextureCacheAllocationKind::Reset(ref info) => {
// Create a new native texture, as requested by the texture cache.
//
// Ensure no PBO is bound when creating the texture storage,
@ -3332,20 +3332,31 @@ impl Renderer {
}
}
let old = self.texture_resolver.texture_cache_map.insert(allocation.id, texture);
assert_eq!(old.is_some(), is_realloc, "Renderer and RenderBackend disagree");
if let Some(old) = old {
self.device.blit_renderable_texture(
self.texture_resolver.texture_cache_map.get_mut(&allocation.id).unwrap(),
&old
);
self.device.delete_texture(old);
}
},
self.texture_resolver.texture_cache_map.insert(allocation.id, texture)
}
TextureCacheAllocationKind::Free => {
let texture = self.texture_resolver.texture_cache_map.remove(&allocation.id).unwrap();
self.device.delete_texture(texture);
},
self.texture_resolver.texture_cache_map.remove(&allocation.id)
}
};
match allocation.kind {
TextureCacheAllocationKind::Alloc(_) => {
assert!(old.is_none(), "Renderer and backend disagree!");
}
TextureCacheAllocationKind::Realloc(_) => {
self.device.blit_renderable_texture(
self.texture_resolver.texture_cache_map.get_mut(&allocation.id).unwrap(),
old.as_ref().unwrap(),
);
}
TextureCacheAllocationKind::Reset(_) |
TextureCacheAllocationKind::Free => {
assert!(old.is_some(), "Renderer and backend disagree!");
}
}
if let Some(old) = old {
self.device.delete_texture(old);
}
}

Просмотреть файл

@ -2183,6 +2183,9 @@ impl ResourceCache {
// and fill out the map as the first step.
let mut raw_map = FastHashMap::<String, Arc<Vec<u8>>>::default();
self.clear(ClearCache::all());
self.clear_images(|_| true);
match caches {
Some(cached) => {
self.current_frame_id = cached.current_frame_id;
@ -2194,10 +2197,6 @@ impl ResourceCache {
}
None => {
self.current_frame_id = FrameId::INVALID;
self.cached_glyphs.clear();
self.cached_glyph_dimensions.clear();
self.cached_images.clear();
self.cached_render_tasks.clear();
self.texture_cache = TextureCache::new(
self.texture_cache.max_texture_size(),
self.texture_cache.max_texture_layers(),

Просмотреть файл

@ -639,7 +639,7 @@ impl TextureCache {
self.clear_kind(EntryKind::Picture);
if let Some(ref mut picture_texture) = self.picture_texture {
if let Some(texture_id) = picture_texture.reset(PICTURE_TEXTURE_ADD_SLICES) {
self.pending_updates.push_realloc(texture_id, picture_texture.to_info());
self.pending_updates.push_reset(texture_id, picture_texture.to_info());
}
}
}

Просмотреть файл

@ -44,6 +44,7 @@ impl<'a> RawtestHarness<'a> {
self.test_blur_cache();
self.test_capture();
self.test_zero_height_window();
self.test_clear_cache();
}
fn render_and_get_pixels(&mut self, window_rect: FramebufferIntRect) -> Vec<u8> {
@ -463,7 +464,7 @@ impl<'a> RawtestHarness<'a> {
}
fn test_offscreen_blob(&mut self) {
println!("\toffscreen blob update.");
println!("\toffscreen blob update...");
assert_eq!(self.wrench.device_pixel_ratio, 1.);
@ -1298,4 +1299,19 @@ impl<'a> RawtestHarness<'a> {
test_rounded_rectangle(WorldPoint::new(200., 100.), WorldSize::new(100., 100.), (0, 5));
}
fn test_clear_cache(&mut self) {
println!("\tclear cache test...");
self.wrench.api.send_message(ApiMsg::DebugCommand(DebugCommand::ClearCaches(ClearCache::all())));
let layout_size = LayoutSize::new(400., 400.);
let builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
let txn = Transaction::new();
let mut epoch = Epoch(0);
self.submit_dl(&mut epoch, layout_size, builder, &txn.resource_updates);
self.rx.recv().unwrap();
self.wrench.render();
}
}