Bug 1607836 - Preallocate picture task dependency vectors. r=gw
authorNicolas Silva <nsilva@mozilla.com>
Sun, 19 Jan 2020 19:32:11 +0000
changeset 510829 dfe4fa983d2b1eaaa3db2141a5e1c0f5ae58d5d7
parent 510828 db0378df4c6616330779c46cd830dd2f76f53b1b
child 510830 38ca681e72de431d863e36cb6de77fbfa102b82f
push id37036
push userdvarga@mozilla.com
push dateTue, 21 Jan 2020 00:17:43 +0000
treeherdermozilla-central@83b429758070 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgw
bugs1607836
milestone74.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1607836 - Preallocate picture task dependency vectors. r=gw Unlike other types of render tasks, pictures can have hundreds of dependencies. The dependency vector is re-built every frame, leading to a lot of vector re-allocations in some pages. Depends on D60151 Differential Revision: https://phabricator.services.mozilla.com/D60182
gfx/wr/webrender/src/frame_builder.rs
gfx/wr/webrender/src/picture.rs
gfx/wr/webrender/src/prim_store/mod.rs
--- a/gfx/wr/webrender/src/frame_builder.rs
+++ b/gfx/wr/webrender/src/frame_builder.rs
@@ -433,16 +433,17 @@ impl FrameBuilder {
                 data_stores,
                 scratch,
                 tile_cache_logger,
             );
         }
 
         let pic = &mut scene.prim_store.pictures[scene.root_pic_index.0];
         pic.restore_context(
+            ROOT_SURFACE_INDEX,
             prim_list,
             pic_context,
             pic_state,
             &mut frame_state,
         );
 
         frame_state.pop_dirty_region();
 
--- a/gfx/wr/webrender/src/picture.rs
+++ b/gfx/wr/webrender/src/picture.rs
@@ -3272,16 +3272,20 @@ pub struct PicturePrimitive {
     pub segments_are_valid: bool,
 
     /// If Some(..) the tile cache that is associated with this picture.
     #[cfg_attr(feature = "capture", serde(skip))] //TODO
     pub tile_cache: Option<Box<TileCacheInstance>>,
 
     /// The config options for this picture.
     pub options: PictureOptions,
+
+    /// Keep track of the number of render tasks dependencies to pre-allocate
+    /// the dependency array next frame.
+    num_render_tasks: usize,
 }
 
 impl PicturePrimitive {
     pub fn print<T: PrintTreePrinter>(
         &self,
         pictures: &[Self],
         self_index: PictureIndex,
         pt: &mut T,
@@ -3414,16 +3418,17 @@ impl PicturePrimitive {
             is_backface_visible: flags.contains(PrimitiveFlags::IS_BACKFACE_VISIBLE),
             requested_raster_space,
             spatial_node_index,
             estimated_local_rect: LayoutRect::zero(),
             precise_local_rect: LayoutRect::zero(),
             tile_cache,
             options,
             segments_are_valid: false,
+            num_render_tasks: 0,
         }
     }
 
     /// Gets the raster space to use when rendering the picture.
     /// Usually this would be the requested raster space. However, if the
     /// picture's spatial node or one of its ancestors is being pinch zoomed
     /// then we round it. This prevents us rasterizing glyphs for every minor
     /// change in zoom level, as that would be too expensive.
@@ -3456,16 +3461,19 @@ impl PicturePrimitive {
         frame_context: &FrameBuildingContext,
         scratch: &mut PrimitiveScratchBuffer,
         tile_cache_logger: &mut TileCacheLogger,
     ) -> Option<(PictureContext, PictureState, PrimitiveList)> {
         if !self.is_visible() {
             return None;
         }
 
+        let task_id = frame_state.surfaces[parent_surface_index.0].render_tasks.unwrap().port;
+        frame_state.render_tasks[task_id].children.reserve(self.num_render_tasks);
+
         // Extract the raster and surface spatial nodes from the raster
         // config, if this picture establishes a surface. Otherwise just
         // pass in the spatial node indices from the parent context.
         let (raster_spatial_node_index, surface_spatial_node_index, surface_index, inflation_factor) = match self.raster_config {
             Some(ref raster_config) => {
                 let surface = &frame_state.surfaces[raster_config.surface_index.0];
 
                 (
@@ -4220,26 +4228,30 @@ impl PicturePrimitive {
 
         let prim_list = mem::replace(&mut self.prim_list, PrimitiveList::empty());
 
         Some((context, state, prim_list))
     }
 
     pub fn restore_context(
         &mut self,
+        parent_surface_index: SurfaceIndex,
         prim_list: PrimitiveList,
         context: PictureContext,
         state: PictureState,
         frame_state: &mut FrameBuildingState,
     ) {
         // Pop any dirty regions this picture set
         for _ in 0 .. context.dirty_region_count {
             frame_state.pop_dirty_region();
         }
 
+        let task_id = frame_state.surfaces[parent_surface_index.0].render_tasks.unwrap().port;
+        self.num_render_tasks = frame_state.render_tasks[task_id].children.len();
+
         self.prim_list = prim_list;
         self.state = Some(state);
     }
 
     pub fn take_state(&mut self) -> PictureState {
         self.state.take().expect("bug: no state present!")
     }
 
--- a/gfx/wr/webrender/src/prim_store/mod.rs
+++ b/gfx/wr/webrender/src/prim_store/mod.rs
@@ -2727,16 +2727,17 @@ impl PrimitiveStore {
                     data_stores,
                     scratch,
                     tile_cache_log,
                 );
 
                 // Restore the dependencies (borrow check dance)
                 self.pictures[pic_context_for_children.pic_index.0]
                     .restore_context(
+                        pic_context.surface_index,
                         prim_list,
                         pic_context_for_children,
                         pic_state_for_children,
                         frame_state,
                     );
 
                 is_passthrough
             }