diff --git a/gfx/wr/webrender/src/clip.rs b/gfx/wr/webrender/src/clip.rs index 396e80ff82da..6ba05473039a 100644 --- a/gfx/wr/webrender/src/clip.rs +++ b/gfx/wr/webrender/src/clip.rs @@ -108,7 +108,7 @@ use crate::prim_store::{ClipData, ImageMaskData, SpaceMapper, VisibleMaskImageTi use crate::prim_store::{PointKey, SizeKey, RectangleKey}; use crate::render_task_cache::to_cache_size; use crate::resource_cache::{ImageRequest, ResourceCache}; -use crate::util::{clamp_to_scale_factor, extract_inner_rect_safe, project_rect, ScaleOffset, VecHelper}; +use crate::util::{clamp_to_scale_factor, extract_inner_rect_safe, project_rect, ScaleOffset}; use euclid::approxeq::ApproxEq; use std::{iter, ops, u32}; use smallvec::SmallVec; @@ -836,25 +836,6 @@ impl ClipChainStack { } } - pub fn clear(&mut self) { - self.clips.clear(); - self.clip_counts.clear(); - self.levels.clear(); - self.levels.push(ClipChainLevel { - shared_clips: Vec::new(), - first_clip_index: 0, - initial_clip_counts_len: 0, - }); - } - - pub fn take(&mut self) -> Self { - ClipChainStack { - levels: self.levels.take(), - clips: self.clips.take(), - clip_counts: self.clip_counts.take(), - } - } - /// Push a clip chain root onto the currently active list. pub fn push_clip( &mut self, diff --git a/gfx/wr/webrender/src/frame_builder.rs b/gfx/wr/webrender/src/frame_builder.rs index 93e01ec0ef59..afb56778c95a 100644 --- a/gfx/wr/webrender/src/frame_builder.rs +++ b/gfx/wr/webrender/src/frame_builder.rs @@ -16,10 +16,10 @@ use crate::internal_types::{FastHashMap, PlaneSplitter, SavedTargetIndex}; use crate::picture::{PictureUpdateState, SurfaceInfo, ROOT_SURFACE_INDEX, SurfaceIndex, RecordedDirtyRegion}; use crate::picture::{RetainedTiles, TileCacheInstance, DirtyRegion, SurfaceRenderTasks, SubpixelMode}; use crate::picture::{BackdropKind, TileCacheLogger}; -use crate::prim_store::{SpaceMapper, PictureIndex, PrimitiveDebugId}; +use crate::prim_store::{SpaceMapper, PictureIndex, PrimitiveDebugId, PrimitiveScratchBuffer}; use crate::prim_store::{DeferredResolve, PrimitiveVisibilityMask}; use crate::profiler::{FrameProfileCounters, TextureCacheProfileCounters, ResourceProfileCounters}; -use crate::render_backend::{DataStores, FrameStamp, FrameId, ScratchBuffer}; +use crate::render_backend::{DataStores, FrameStamp, FrameId}; use crate::render_target::{RenderTarget, PictureCacheTarget, TextureCacheRenderTarget}; use crate::render_target::{RenderTargetContext, RenderTargetKind}; use crate::render_task_graph::{RenderTaskId, RenderTaskGraph, RenderTaskGraphCounters}; @@ -29,7 +29,7 @@ use crate::resource_cache::{ResourceCache}; use crate::scene::{BuiltScene, SceneProperties}; use crate::segment::SegmentBuilder; use std::{f32, mem}; -use crate::util::{MaxRect, VecHelper, Recycler}; +use crate::util::MaxRect; #[derive(Clone, Copy, Debug, PartialEq)] @@ -114,43 +114,6 @@ impl FrameGlobalResources { } } -pub struct FrameScratchBuffer { - surfaces: Vec, - dirty_region_stack: Vec, - surface_stack: Vec, - clip_chain_stack: ClipChainStack, -} - -impl Default for FrameScratchBuffer { - fn default() -> Self { - FrameScratchBuffer { - surfaces: Vec::new(), - dirty_region_stack: Vec::new(), - surface_stack: Vec::new(), - clip_chain_stack: ClipChainStack::new(), - } - } -} - -impl FrameScratchBuffer { - pub fn begin_frame(&mut self) { - self.surfaces.clear(); - self.dirty_region_stack.clear(); - self.surface_stack.clear(); - self.clip_chain_stack.clear(); - } - - pub fn recycle(&mut self, recycler: &mut Recycler) { - recycler.recycle_vec(&mut self.surfaces); - // Don't call recycle on the stacks because the reycler's - // role is to get rid of allocations when the capacity - // is much larger than the lengths. with stacks the - // length varies through the frame but is supposedly - // back to zero by the end so we would always throw the - // allocation away. - } -} - /// Produces the frames that are sent to the renderer. #[cfg_attr(feature = "capture", derive(Serialize))] pub struct FrameBuilder { @@ -171,19 +134,19 @@ pub struct FrameVisibilityContext<'a> { } pub struct FrameVisibilityState<'a> { - pub clip_chain_stack: ClipChainStack, - /// A stack of currently active off-screen surfaces during the - /// visibility frame traversal. - pub surface_stack: Vec, pub clip_store: &'a mut ClipStore, pub resource_cache: &'a mut ResourceCache, pub gpu_cache: &'a mut GpuCache, - pub scratch: &'a mut ScratchBuffer, + pub scratch: &'a mut PrimitiveScratchBuffer, pub tile_cache: Option>, pub retained_tiles: &'a mut RetainedTiles, pub data_stores: &'a mut DataStores, + pub clip_chain_stack: ClipChainStack, pub render_tasks: &'a mut RenderTaskGraph, pub composite_state: &'a mut CompositeState, + /// A stack of currently active off-screen surfaces during the + /// visibility frame traversal. + pub surface_stack: Vec, } impl<'a> FrameVisibilityState<'a> { @@ -306,7 +269,8 @@ impl FrameBuilder { scene_properties: &SceneProperties, transform_palette: &mut TransformPalette, data_stores: &mut DataStores, - scratch: &mut ScratchBuffer, + surfaces: &mut Vec, + scratch: &mut PrimitiveScratchBuffer, debug_flags: DebugFlags, texture_cache_profile: &mut TextureCacheProfileCounters, composite_state: &mut CompositeState, @@ -363,7 +327,6 @@ impl FrameBuilder { global_device_pixel_scale, (1.0, 1.0), ); - let mut surfaces = scratch.frame.surfaces.take(); surfaces.push(root_surface); let mut retained_tiles = mem::replace( @@ -379,8 +342,7 @@ impl FrameBuilder { // which surfaces have valid cached surfaces that don't need to // be rendered this frame. PictureUpdateState::update_all( - &mut scratch.picture, - &mut surfaces, + surfaces, scene.root_pic_index, &mut scene.prim_store.pictures, &frame_context, @@ -398,15 +360,13 @@ impl FrameBuilder { global_device_pixel_scale, spatial_tree: &scene.spatial_tree, global_screen_world_rect, - surfaces: &mut surfaces, + surfaces, debug_flags, scene_properties, config: scene.config, }; let mut visibility_state = FrameVisibilityState { - clip_chain_stack: scratch.frame.clip_chain_stack.take(), - surface_stack: scratch.frame.surface_stack.take(), resource_cache, gpu_cache, clip_store: &mut scene.clip_store, @@ -414,8 +374,12 @@ impl FrameBuilder { tile_cache: None, retained_tiles: &mut retained_tiles, data_stores, + clip_chain_stack: ClipChainStack::new(), render_tasks, composite_state, + /// Try to avoid allocating during frame traversal - it's unlikely to have a + /// surface stack depth of > 16 in most cases. + surface_stack: Vec::with_capacity(16), }; scene.prim_store.update_visibility( @@ -452,9 +416,6 @@ impl FrameBuilder { visibility_state.resource_cache.destroy_compositor_surface(external_surface.native_surface_id) } } - - visibility_state.scratch.frame.clip_chain_stack = visibility_state.clip_chain_stack.take(); - visibility_state.scratch.frame.surface_stack = visibility_state.surface_stack.take(); } let mut frame_state = FrameBuildingState { @@ -465,8 +426,8 @@ impl FrameBuilder { gpu_cache, transforms: transform_palette, segment_builder: SegmentBuilder::new(), - surfaces: &mut surfaces, - dirty_region_stack: scratch.frame.dirty_region_stack.take(), + surfaces, + dirty_region_stack: Vec::new(), composite_state, }; @@ -501,7 +462,7 @@ impl FrameBuilder { &SubpixelMode::Allow, &mut frame_state, &frame_context, - &mut scratch.primitive, + scratch, tile_cache_logger ) .unwrap(); @@ -518,7 +479,7 @@ impl FrameBuilder { &frame_context, &mut frame_state, data_stores, - &mut scratch.primitive, + scratch, tile_cache_logger, ); } @@ -534,9 +495,6 @@ impl FrameBuilder { frame_state.pop_dirty_region(); - scratch.frame.dirty_region_stack = frame_state.dirty_region_stack.take(); - scratch.frame.surfaces = surfaces.take(); - { profile_marker!("BlockOnResources"); @@ -561,7 +519,7 @@ impl FrameBuilder { resource_profile: &mut ResourceProfileCounters, scene_properties: &SceneProperties, data_stores: &mut DataStores, - scratch: &mut ScratchBuffer, + scratch: &mut PrimitiveScratchBuffer, render_task_counters: &mut RenderTaskGraphCounters, debug_flags: DebugFlags, tile_cache_logger: &mut TileCacheLogger, @@ -591,6 +549,7 @@ impl FrameBuilder { stamp.frame_id(), render_task_counters, ); + let mut surfaces = Vec::new(); let output_size = scene.output_rect.size.to_i32(); let screen_world_rect = (scene.output_rect.to_f32() / global_device_pixel_scale).round_out(); @@ -628,6 +587,7 @@ impl FrameBuilder { scene_properties, &mut transform_palette, data_stores, + &mut surfaces, scratch, debug_flags, &mut resource_profile.texture_cache, @@ -665,8 +625,8 @@ impl FrameBuilder { batch_lookback_count: scene.config.batch_lookback_count, spatial_tree: &scene.spatial_tree, data_stores, - surfaces: &scratch.frame.surfaces, - scratch: &mut scratch.primitive, + surfaces: &surfaces, + scratch, screen_world_rect, globals: &self.globals, }; @@ -720,8 +680,8 @@ impl FrameBuilder { has_been_rendered: false, has_texture_cache_tasks, prim_headers, - recorded_dirty_regions: mem::replace(&mut scratch.primitive.recorded_dirty_regions, Vec::new()), - debug_items: mem::replace(&mut scratch.primitive.debug_items, Vec::new()), + recorded_dirty_regions: mem::replace(&mut scratch.recorded_dirty_regions, Vec::new()), + debug_items: mem::replace(&mut scratch.debug_items, Vec::new()), composite_state, } } diff --git a/gfx/wr/webrender/src/picture.rs b/gfx/wr/webrender/src/picture.rs index 96812579318b..ec19640ed41b 100644 --- a/gfx/wr/webrender/src/picture.rs +++ b/gfx/wr/webrender/src/picture.rs @@ -133,7 +133,7 @@ use std::{mem, u8, marker, u32}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::collections::hash_map::Entry; use crate::texture_cache::TextureCacheHandle; -use crate::util::{MaxRect, VecHelper, RectHelpers, MatrixHelpers, Recycler}; +use crate::util::{MaxRect, VecHelper, RectHelpers, MatrixHelpers}; use crate::filterdata::{FilterDataHandle}; #[cfg(any(feature = "capture", feature = "replay"))] use ron; @@ -2512,9 +2512,7 @@ impl TileCacheInstance { // which will provide a local clip rect. This is useful for establishing things // like whether the backdrop rect supplied by Gecko can be considered opaque. if self.shared_clip_chain != ClipChainId::NONE { - let shared_clips = &mut frame_state.scratch.picture.clip_chain_ids; - shared_clips.clear(); - + let mut shared_clips = Vec::new(); let mut current_clip_chain_id = self.shared_clip_chain; while current_clip_chain_id != ClipChainId::NONE { shared_clips.push(current_clip_chain_id); @@ -3814,40 +3812,11 @@ impl TileCacheInstance { // When under test, record a copy of the dirty region to support // invalidation testing in wrench. if frame_context.config.testing { - frame_state.scratch.primitive.recorded_dirty_regions.push(self.dirty_region.record()); + frame_state.scratch.recorded_dirty_regions.push(self.dirty_region.record()); } } } -pub struct PictureScratchBuffer { - surface_stack: Vec, - picture_stack: Vec, - clip_chain_ids: Vec, -} - -impl Default for PictureScratchBuffer { - fn default() -> Self { - PictureScratchBuffer { - surface_stack: Vec::new(), - picture_stack: Vec::new(), - clip_chain_ids: Vec::new(), - } - } -} - -impl PictureScratchBuffer { - pub fn begin_frame(&mut self) { - self.surface_stack.clear(); - self.picture_stack.clear(); - self.clip_chain_ids.clear(); - } - - pub fn recycle(&mut self, recycler: &mut Recycler) { - recycler.recycle_vec(&mut self.surface_stack); - recycler.recycle_vec(&mut self.picture_stack); - } - } - /// Maintains a stack of picture and surface information, that /// is used during the initial picture traversal. pub struct PictureUpdateState<'a> { @@ -3860,7 +3829,6 @@ pub struct PictureUpdateState<'a> { impl<'a> PictureUpdateState<'a> { pub fn update_all( - buffers: &mut PictureScratchBuffer, surfaces: &'a mut Vec, pic_index: PictureIndex, picture_primitives: &mut [PicturePrimitive], @@ -3875,14 +3843,12 @@ impl<'a> PictureUpdateState<'a> { let mut state = PictureUpdateState { surfaces, - surface_stack: buffers.surface_stack.take().cleared(), - picture_stack: buffers.picture_stack.take().cleared(), + surface_stack: vec![SurfaceIndex(0)], + picture_stack: Vec::new(), are_raster_roots_assigned: true, composite_state, }; - state.surface_stack.push(SurfaceIndex(0)); - state.update( pic_index, picture_primitives, @@ -3899,9 +3865,6 @@ impl<'a> PictureUpdateState<'a> { ROOT_SPATIAL_NODE_INDEX, ); } - - buffers.surface_stack = state.surface_stack.take(); - buffers.picture_stack = state.picture_stack.take(); } /// Return the current surface diff --git a/gfx/wr/webrender/src/prim_store/mod.rs b/gfx/wr/webrender/src/prim_store/mod.rs index b3082425d2b7..83237d316e0b 100644 --- a/gfx/wr/webrender/src/prim_store/mod.rs +++ b/gfx/wr/webrender/src/prim_store/mod.rs @@ -1654,8 +1654,8 @@ pub struct PrimitiveScratchBuffer { pub debug_items: Vec, } -impl Default for PrimitiveScratchBuffer { - fn default() -> Self { +impl PrimitiveScratchBuffer { + pub fn new() -> Self { PrimitiveScratchBuffer { clip_mask_instances: Vec::new(), glyph_keys: GlyphKeyStorage::new(0), @@ -1668,9 +1668,7 @@ impl Default for PrimitiveScratchBuffer { prim_info: Vec::new(), } } -} -impl PrimitiveScratchBuffer { pub fn recycle(&mut self, recycler: &mut Recycler) { recycler.recycle_vec(&mut self.clip_mask_instances); recycler.recycle_vec(&mut self.prim_info); @@ -1992,9 +1990,9 @@ impl PrimitiveStore { }; if is_passthrough { - let vis_index = PrimitiveVisibilityIndex(frame_state.scratch.primitive.prim_info.len() as u32); + let vis_index = PrimitiveVisibilityIndex(frame_state.scratch.prim_info.len() as u32); - frame_state.scratch.primitive.prim_info.push( + frame_state.scratch.prim_info.push( PrimitiveVisibility { clipped_world_rect: WorldRect::max_rect(), clip_chain: ClipChainInstance::empty(), @@ -2193,7 +2191,7 @@ impl PrimitiveStore { }; if debug_color.a != 0.0 { let debug_rect = clipped_world_rect * frame_context.global_device_pixel_scale; - frame_state.scratch.primitive.push_debug_rect(debug_rect, debug_color, debug_color.scale_alpha(0.5)); + frame_state.scratch.push_debug_rect(debug_rect, debug_color, debug_color.scale_alpha(0.5)); } } else if frame_context.debug_flags.contains(::api::DebugFlags::OBSCURE_IMAGES) { let is_image = matches!( @@ -2204,17 +2202,17 @@ impl PrimitiveStore { // We allow "small" images, since they're generally UI elements. let rect = clipped_world_rect * frame_context.global_device_pixel_scale; if rect.size.width > 70.0 && rect.size.height > 70.0 { - frame_state.scratch.primitive.push_debug_rect(rect, debug_colors::PURPLE, debug_colors::PURPLE); + frame_state.scratch.push_debug_rect(rect, debug_colors::PURPLE, debug_colors::PURPLE); } } } - let vis_index = PrimitiveVisibilityIndex(frame_state.scratch.primitive.prim_info.len() as u32); + let vis_index = PrimitiveVisibilityIndex(frame_state.scratch.prim_info.len() as u32); if prim_instance.is_chased() { println!("\tvisible {:?} with {:?}", vis_index, combined_local_clip_rect); } - frame_state.scratch.primitive.prim_info.push( + frame_state.scratch.prim_info.push( PrimitiveVisibility { clipped_world_rect, clip_chain, @@ -2367,7 +2365,7 @@ impl PrimitiveStore { // Tighten the clip rect because decomposing the repeated image can // produce primitives that are partially covering the original image // rect and we want to clip these extra parts out. - let prim_info = &frame_state.scratch.primitive.prim_info[prim_instance.visibility_info.0 as usize]; + let prim_info = &frame_state.scratch.prim_info[prim_instance.visibility_info.0 as usize]; let tight_clip_rect = prim_info .combined_local_clip_rect .intersection(&common_data.prim_rect).unwrap(); diff --git a/gfx/wr/webrender/src/render_backend.rs b/gfx/wr/webrender/src/render_backend.rs index c7b33ccb0635..66ad336bef76 100644 --- a/gfx/wr/webrender/src/render_backend.rs +++ b/gfx/wr/webrender/src/render_backend.rs @@ -25,14 +25,14 @@ use crate::capture::CaptureConfig; use crate::composite::{CompositorKind, CompositeDescriptor}; #[cfg(feature = "debugger")] use crate::debug_server; -use crate::frame_builder::{FrameBuilder, FrameBuilderConfig, FrameScratchBuffer}; +use crate::frame_builder::{FrameBuilder, FrameBuilderConfig}; use crate::glyph_rasterizer::{FontInstance}; use crate::gpu_cache::GpuCache; use crate::hit_test::{HitTest, HitTester, SharedHitTester}; use crate::intern::DataStore; use crate::internal_types::{DebugOutput, FastHashMap, RenderedDocument, ResultMsg}; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; -use crate::picture::{RetainedTiles, TileCacheLogger, PictureScratchBuffer}; +use crate::picture::{RetainedTiles, TileCacheLogger}; use crate::prim_store::{PrimitiveScratchBuffer, PrimitiveInstance}; use crate::prim_store::{PrimitiveInstanceKind, PrimTemplateCommonData, PrimitiveStore}; use crate::prim_store::interned::*; @@ -383,31 +383,6 @@ impl DataStores { } } -#[derive(Default)] -pub struct ScratchBuffer { - pub primitive: PrimitiveScratchBuffer, - pub picture: PictureScratchBuffer, - pub frame: FrameScratchBuffer, -} - -impl ScratchBuffer { - pub fn begin_frame(&mut self) { - self.primitive.begin_frame(); - self.picture.begin_frame(); - self.frame.begin_frame(); - } - - pub fn recycle(&mut self, recycler: &mut Recycler) { - self.primitive.recycle(recycler); - self.picture.recycle(recycler); - self.frame.recycle(recycler); - } - - pub fn memory_pressure(&mut self) { - *self = Self::default(); - } -} - struct Document { /// The id of this document id: DocumentId, @@ -453,7 +428,7 @@ struct Document { /// Contains various vecs of data that is used only during frame building, /// where we want to recycle the memory each new display list, to avoid constantly /// re-allocating and moving memory around. - scratch: ScratchBuffer, + scratch: PrimitiveScratchBuffer, /// Keep track of the size of render task graph to pre-allocate memory up-front /// the next frame. render_task_counters: RenderTaskGraphCounters, @@ -499,7 +474,7 @@ impl Document { rendered_frame_is_valid: false, has_built_scene: false, data_stores: DataStores::default(), - scratch: ScratchBuffer::default(), + scratch: PrimitiveScratchBuffer::new(), render_task_counters: RenderTaskGraphCounters::new(), #[cfg(feature = "replay")] loaded_scene: Scene::new(), @@ -1165,10 +1140,6 @@ impl RenderBackend { self.gpu_cache.clear(); - for (_, doc) in &mut self.documents { - doc.scratch.memory_pressure(); - } - let resource_updates = self.resource_cache.pending_updates(); let msg = ResultMsg::UpdateResources { resource_updates, @@ -1782,7 +1753,7 @@ impl RenderBackend { let file_name = format!("built-clips-{}-{}", id.namespace_id.0, id.id); config.serialize_for_frame(&doc.scene.clip_store, file_name); let file_name = format!("scratch-{}-{}", id.namespace_id.0, id.id); - config.serialize_for_frame(&doc.scratch.primitive, file_name); + config.serialize_for_frame(&doc.scratch, file_name); let file_name = format!("render-tasks-{}-{}.svg", id.namespace_id.0, id.id); let mut svg_file = fs::File::create(&config.file_path_for_frame(file_name, "svg")) .expect("Failed to open the SVG file."); @@ -1982,7 +1953,7 @@ impl RenderBackend { rendered_frame_is_valid: false, has_built_scene: false, data_stores, - scratch: ScratchBuffer::default(), + scratch: PrimitiveScratchBuffer::new(), render_task_counters: RenderTaskGraphCounters::new(), loaded_scene: scene.clone(), prev_composite_descriptor: CompositeDescriptor::empty(), diff --git a/gfx/wr/webrender/src/segment.rs b/gfx/wr/webrender/src/segment.rs index 553d516b7615..77bca528215d 100644 --- a/gfx/wr/webrender/src/segment.rs +++ b/gfx/wr/webrender/src/segment.rs @@ -331,8 +331,6 @@ impl SegmentBuilder { ), ]; - self.items.reserve(segments.len() + 1); - for segment in segments { self.items.push(Item::new( *segment, @@ -380,8 +378,6 @@ impl SegmentBuilder { let p2 = inner.bottom_right(); let p3 = rect.bottom_right(); - self.items.reserve(9); - let corner_segments = &[ LayoutRect::new( LayoutPoint::new(p0.x, p0.y), diff --git a/gfx/wr/webrender/src/util.rs b/gfx/wr/webrender/src/util.rs index dc3d04915385..f18b80a45df5 100644 --- a/gfx/wr/webrender/src/util.rs +++ b/gfx/wr/webrender/src/util.rs @@ -66,9 +66,6 @@ pub trait VecHelper { /// Equivalent to `mem::replace(&mut vec, Vec::new())` fn take(&mut self) -> Self; - /// Call clear and return self (useful for chaining with calls that move the vector). - fn cleared(self) -> Self; - /// Functionally equivalent to `mem::replace(&mut vec, Vec::new())` but tries /// to keep the allocation in the caller if it is empty or replace it with a /// pre-allocated vector. @@ -102,12 +99,6 @@ impl VecHelper for Vec { replace(self, Vec::new()) } - fn cleared(mut self) -> Self { - self.clear(); - - self - } - fn take_and_preallocate(&mut self) -> Self { let len = self.len(); if len == 0 {