| author | Nicolas Silva <nsilva@mozilla.com> |
| Thu, 23 Jan 2020 19:26:13 +0000 | |
| changeset 511570 | e30053699db0bc3c77888e789f0ba576f0904d1f |
| parent 511569 | 686c9a8825377021ef9aa445b22b759800dc6546 |
| child 511571 | 4a6071f143a5ffca548f745084b5652c40f66829 |
| push id | 37049 |
| push user | rmaries@mozilla.com |
| push date | Fri, 24 Jan 2020 03:50:24 +0000 |
| treeherder | mozilla-central@e05793f68994 [default view] [failures only] |
| perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
| reviewers | gw |
| bugs | 1611176 |
| milestone | 74.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
|
--- a/gfx/wr/webrender/src/frame_builder.rs +++ b/gfx/wr/webrender/src/frame_builder.rs @@ -265,30 +265,30 @@ impl FrameBuilder { max_local_clip: LayoutRect::new( LayoutPoint::new(-MAX_CLIP_COORD, -MAX_CLIP_COORD), LayoutSize::new(2.0 * MAX_CLIP_COORD, 2.0 * MAX_CLIP_COORD), ), debug_flags, fb_config: &scene.config, }; - let root_render_task = RenderTask::new_picture( - RenderTaskLocation::Fixed(scene.output_rect), - scene.output_rect.size.to_f32(), - scene.root_pic_index, - DeviceIntPoint::zero(), - UvRectKind::Rect, - ROOT_SPATIAL_NODE_INDEX, - global_device_pixel_scale, - PrimitiveVisibilityMask::all(), - None, + let root_render_task_id = render_tasks.add().init( + RenderTask::new_picture( + RenderTaskLocation::Fixed(scene.output_rect), + scene.output_rect.size.to_f32(), + scene.root_pic_index, + DeviceIntPoint::zero(), + UvRectKind::Rect, + ROOT_SPATIAL_NODE_INDEX, + global_device_pixel_scale, + PrimitiveVisibilityMask::all(), + None, + ) ); - let root_render_task_id = render_tasks.add(root_render_task); - // Construct a dummy root surface, that represents the // main framebuffer surface. let root_surface = SurfaceInfo::new( ROOT_SPATIAL_NODE_INDEX, ROOT_SPATIAL_NODE_INDEX, 0.0, global_screen_world_rect, &scene.clip_scroll_tree,
--- a/gfx/wr/webrender/src/picture.rs +++ b/gfx/wr/webrender/src/picture.rs @@ -3750,30 +3750,30 @@ impl PicturePrimitive { let uv_rect_kind = calculate_uv_rect_kind( &pic_rect, &transform, &device_rect, device_pixel_scale, true, ); - let picture_task = RenderTask::new_picture( - RenderTaskLocation::Dynamic(None, device_rect.size), - unclipped.size, - pic_index, - device_rect.origin, - uv_rect_kind, - surface_spatial_node_index, - device_pixel_scale, - PrimitiveVisibilityMask::all(), - None, + let picture_task_id = frame_state.render_tasks.add().init( + RenderTask::new_picture( + RenderTaskLocation::Dynamic(None, device_rect.size), + unclipped.size, + pic_index, + device_rect.origin, + uv_rect_kind, + surface_spatial_node_index, + device_pixel_scale, + PrimitiveVisibilityMask::all(), + None, + ) ); - let picture_task_id = frame_state.render_tasks.add(picture_task); - let blur_render_task_id = RenderTask::new_blur( blur_std_deviation, picture_task_id, frame_state.render_tasks, RenderTargetKind::Color, ClearMode::Transparent, None, original_size, @@ -3813,30 +3813,32 @@ impl PicturePrimitive { let uv_rect_kind = calculate_uv_rect_kind( &pic_rect, &transform, &device_rect, device_pixel_scale, true, ); - let mut picture_task = RenderTask::new_picture( - RenderTaskLocation::Dynamic(None, device_rect.size), - unclipped.size, - pic_index, - device_rect.origin, - uv_rect_kind, - surface_spatial_node_index, - device_pixel_scale, - PrimitiveVisibilityMask::all(), - None, - ); - picture_task.mark_for_saving(); - - let picture_task_id = frame_state.render_tasks.add(picture_task); + let picture_task_id = frame_state.render_tasks.add().init({ + let mut picture_task = RenderTask::new_picture( + RenderTaskLocation::Dynamic(None, device_rect.size), + unclipped.size, + pic_index, + device_rect.origin, + uv_rect_kind, + surface_spatial_node_index, + device_pixel_scale, + PrimitiveVisibilityMask::all(), + None, + ); + picture_task.mark_for_saving(); + + picture_task + }); self.secondary_render_task_id = Some(picture_task_id); let mut blur_tasks = BlurTaskCache::default(); self.extra_gpu_data_handles.resize(shadows.len(), GpuCacheHandle::new()); let mut blur_render_task_id = picture_task_id; @@ -3860,91 +3862,91 @@ impl PicturePrimitive { let uv_rect_kind = calculate_uv_rect_kind( &pic_rect, &transform, &clipped, device_pixel_scale, true, ); - let picture_task = RenderTask::new_picture( - RenderTaskLocation::Dynamic(None, clipped.size), - unclipped.size, - pic_index, - clipped.origin, - uv_rect_kind, - surface_spatial_node_index, - device_pixel_scale, - PrimitiveVisibilityMask::all(), - None, - ); - - let readback_task_id = frame_state.render_tasks.add( + let readback_task_id = frame_state.render_tasks.add().init( RenderTask::new_readback(clipped) ); frame_state.render_tasks.add_dependency( frame_state.surfaces[parent_surface_index.0].render_tasks.unwrap().port, readback_task_id, ); self.secondary_render_task_id = Some(readback_task_id); - let render_task_id = frame_state.render_tasks.add(picture_task); + let render_task_id = frame_state.render_tasks.add().init( + RenderTask::new_picture( + RenderTaskLocation::Dynamic(None, clipped.size), + unclipped.size, + pic_index, + clipped.origin, + uv_rect_kind, + surface_spatial_node_index, + device_pixel_scale, + PrimitiveVisibilityMask::all(), + None, + ) + ); Some((render_task_id, render_task_id)) } PictureCompositeMode::Filter(..) => { let uv_rect_kind = calculate_uv_rect_kind( &pic_rect, &transform, &clipped, device_pixel_scale, true, ); - let picture_task = RenderTask::new_picture( - RenderTaskLocation::Dynamic(None, clipped.size), - unclipped.size, - pic_index, - clipped.origin, - uv_rect_kind, - surface_spatial_node_index, - device_pixel_scale, - PrimitiveVisibilityMask::all(), - None, + let render_task_id = frame_state.render_tasks.add().init( + RenderTask::new_picture( + RenderTaskLocation::Dynamic(None, clipped.size), + unclipped.size, + pic_index, + clipped.origin, + uv_rect_kind, + surface_spatial_node_index, + device_pixel_scale, + PrimitiveVisibilityMask::all(), + None, + ) ); - let render_task_id = frame_state.render_tasks.add(picture_task); - Some((render_task_id, render_task_id)) } PictureCompositeMode::ComponentTransferFilter(..) => { let uv_rect_kind = calculate_uv_rect_kind( &pic_rect, &transform, &clipped, device_pixel_scale, true, ); - let picture_task = RenderTask::new_picture( - RenderTaskLocation::Dynamic(None, clipped.size), - unclipped.size, - pic_index, - clipped.origin, - uv_rect_kind, - surface_spatial_node_index, - device_pixel_scale, - PrimitiveVisibilityMask::all(), - None, + let render_task_id = frame_state.render_tasks.add().init( + RenderTask::new_picture( + RenderTaskLocation::Dynamic(None, clipped.size), + unclipped.size, + pic_index, + clipped.origin, + uv_rect_kind, + surface_spatial_node_index, + device_pixel_scale, + PrimitiveVisibilityMask::all(), + None, + ) ); - let render_task_id = frame_state.render_tasks.add(picture_task); - Some((render_task_id, render_task_id)) } PictureCompositeMode::TileCache { .. } => { let tile_cache = self.tile_cache.as_mut().unwrap(); let mut first = true; // Get the overall world space rect of the picture cache. Used to clip // the tile rects below for occlusion testing to the relevant area. @@ -4133,33 +4135,33 @@ impl PicturePrimitive { // CPUs). Round the rect here before casting to integer device pixels // to ensure the scissor rect is correct. let scissor_rect = (scissor_rect * device_pixel_scale).round(); let surface = descriptor.resolve( frame_state.resource_cache, tile_cache.current_tile_size, ); - let task = RenderTask::new_picture( - RenderTaskLocation::PictureCache { - size: tile_cache.current_tile_size, - surface, - }, - tile_cache.current_tile_size.to_f32(), - pic_index, - content_origin.to_i32(), - UvRectKind::Rect, - surface_spatial_node_index, - device_pixel_scale, - *visibility_mask, - Some(scissor_rect.to_i32()), + let render_task_id = frame_state.render_tasks.add().init( + RenderTask::new_picture( + RenderTaskLocation::PictureCache { + size: tile_cache.current_tile_size, + surface, + }, + tile_cache.current_tile_size.to_f32(), + pic_index, + content_origin.to_i32(), + UvRectKind::Rect, + surface_spatial_node_index, + device_pixel_scale, + *visibility_mask, + Some(scissor_rect.to_i32()), + ) ); - let render_task_id = frame_state.render_tasks.add(task); - frame_state.render_tasks.add_dependency( frame_state.surfaces[parent_surface_index.0].render_tasks.unwrap().port, render_task_id, ); if first { // TODO(gw): Maybe we can restructure this code to avoid the // first hack here. Or at least explain it with a follow up @@ -4197,55 +4199,55 @@ impl PicturePrimitive { let uv_rect_kind = calculate_uv_rect_kind( &pic_rect, &transform, &clipped, device_pixel_scale, supports_snapping, ); - let picture_task = RenderTask::new_picture( - RenderTaskLocation::Dynamic(None, clipped.size), - unclipped.size, - pic_index, - clipped.origin, - uv_rect_kind, - surface_spatial_node_index, - device_pixel_scale, - PrimitiveVisibilityMask::all(), - None, + let render_task_id = frame_state.render_tasks.add().init( + RenderTask::new_picture( + RenderTaskLocation::Dynamic(None, clipped.size), + unclipped.size, + pic_index, + clipped.origin, + uv_rect_kind, + surface_spatial_node_index, + device_pixel_scale, + PrimitiveVisibilityMask::all(), + None, + ) ); - let render_task_id = frame_state.render_tasks.add(picture_task); - Some((render_task_id, render_task_id)) } PictureCompositeMode::SvgFilter(ref primitives, ref filter_datas) => { let uv_rect_kind = calculate_uv_rect_kind( &pic_rect, &transform, &clipped, device_pixel_scale, true, ); - let picture_task = RenderTask::new_picture( - RenderTaskLocation::Dynamic(None, clipped.size), - unclipped.size, - pic_index, - clipped.origin, - uv_rect_kind, - surface_spatial_node_index, - device_pixel_scale, - PrimitiveVisibilityMask::all(), - None, + let picture_task_id = frame_state.render_tasks.add().init( + RenderTask::new_picture( + RenderTaskLocation::Dynamic(None, clipped.size), + unclipped.size, + pic_index, + clipped.origin, + uv_rect_kind, + surface_spatial_node_index, + device_pixel_scale, + PrimitiveVisibilityMask::all(), + None, + ) ); - let picture_task_id = frame_state.render_tasks.add(picture_task); - let filter_task_id = RenderTask::new_svg_filter( primitives, filter_datas, &mut frame_state.render_tasks, clipped.size, uv_rect_kind, picture_task_id, device_pixel_scale,
--- a/gfx/wr/webrender/src/prim_store/image.rs +++ b/gfx/wr/webrender/src/prim_store/image.rs @@ -232,45 +232,34 @@ impl ImageData { frame_state.gpu_cache, frame_state.render_tasks, None, image_properties.descriptor.is_opaque(), |render_tasks| { // Create a task to blit from the texture cache to // a normal transient render task surface. This will // copy only the sub-rect, if specified. - let cache_to_target_task = if false { - // TODO: figure out if/when this can be used - RenderTask::new_blit_with_padding( - *size, - padding, - BlitSource::Image { key: image_cache_key }, - ) - } else { - RenderTask::new_scaling_with_padding( - BlitSource::Image { key: image_cache_key }, - render_tasks, - target_kind, - *size, - padding, - ) - }; - let cache_to_target_task_id = render_tasks.add(cache_to_target_task); + // TODO: figure out if/when we can do a blit instead. + let cache_to_target_task_id = RenderTask::new_scaling_with_padding( + BlitSource::Image { key: image_cache_key }, + render_tasks, + target_kind, + *size, + padding, + ); // Create a task to blit the rect from the child render // task above back into the right spot in the persistent // render target cache. - let target_to_cache_task = RenderTask::new_blit( + render_tasks.add().init(RenderTask::new_blit( *size, BlitSource::RenderTask { task_id: cache_to_target_task_id, }, - ); - - render_tasks.add(target_to_cache_task) + )) } )); } ImageSource::Default => {} } if is_opaque { PrimitiveOpacity::from_alpha(self.color.a)
--- a/gfx/wr/webrender/src/prim_store/mod.rs +++ b/gfx/wr/webrender/src/prim_store/mod.rs @@ -1058,30 +1058,28 @@ impl BrushSegment { device_pixel_scale, ) { Some(info) => info, None => { return ClipMaskKind::Clipped; } }; - let clip_task = RenderTask::new_mask( + let clip_task_id = RenderTask::new_mask( device_rect.to_i32(), clip_chain.clips_range, root_spatial_node_index, frame_state.clip_store, frame_state.gpu_cache, frame_state.resource_cache, frame_state.render_tasks, clip_data_store, device_pixel_scale, frame_context.fb_config, ); - - let clip_task_id = frame_state.render_tasks.add(clip_task); let port = frame_state .surfaces[surface_index.0] .render_tasks .unwrap_or_else(|| panic!("bug: no task for surface {:?}", surface_index)) .port; frame_state.render_tasks.add_dependency(port, clip_task_id); ClipMaskKind::Mask(clip_task_id) } @@ -2898,24 +2896,23 @@ impl PrimitiveStore { size: task_size, kind: RenderTaskCacheKeyKind::LineDecoration(cache_key.clone()), }, frame_state.gpu_cache, frame_state.render_tasks, None, false, |render_tasks| { - let task = RenderTask::new_line_decoration( + render_tasks.add().init(RenderTask::new_line_decoration( task_size, cache_key.style, cache_key.orientation, cache_key.wavy_line_thickness.to_f32_px(), LayoutSize::from_au(cache_key.size), - ); - render_tasks.add(task) + )) } )); } } PrimitiveInstanceKind::TextRun { run_index, data_handle, .. } => { let prim_data = &mut data_stores.text_run[*data_handle]; let run = &mut self.text_runs[*run_index]; @@ -3020,27 +3017,25 @@ impl PrimitiveStore { handles.push(frame_state.resource_cache.request_render_task( cache_key, frame_state.gpu_cache, frame_state.render_tasks, None, false, // TODO(gw): We don't calculate opacity for borders yet! |render_tasks| { - let task = RenderTask::new_border_segment( + render_tasks.add().init(RenderTask::new_border_segment( cache_size, build_border_instances( &segment.cache_key, cache_size, &border_data.border, scale, ), - ); - - render_tasks.add(task) + )) } )); } *cache_handles = scratch .border_cache_handles .extend(handles); } @@ -3202,25 +3197,23 @@ impl PrimitiveStore { size, kind: RenderTaskCacheKeyKind::Gradient(cache_key), }, frame_state.gpu_cache, frame_state.render_tasks, None, prim_data.stops_opacity.is_opaque, |render_tasks| { - let task = RenderTask::new_gradient( + render_tasks.add().init(RenderTask::new_gradient( size, stops, orientation, start_point, end_point, - ); - - render_tasks.add(task) + )) } )); } if prim_data.tile_spacing != LayoutSize::zero() { // We are performing the decomposition on the CPU here, no need to // have it in the shader. prim_data.common.may_need_repetition = false; @@ -4019,30 +4012,28 @@ impl PrimitiveInstance { // need to allocate for the clip mask, as well as interpolated // snap offsets. if let Some(device_rect) = get_clipped_device_rect( &unclipped, &pic_state.map_raster_to_world, prim_info.clipped_world_rect, device_pixel_scale, ) { - let clip_task = RenderTask::new_mask( + let clip_task_id = RenderTask::new_mask( device_rect, prim_info.clip_chain.clips_range, root_spatial_node_index, frame_state.clip_store, frame_state.gpu_cache, frame_state.resource_cache, frame_state.render_tasks, &mut data_stores.clip, device_pixel_scale, frame_context.fb_config, ); - - let clip_task_id = frame_state.render_tasks.add(clip_task); if self.is_chased() { println!("\tcreated task {:?} with device rect {:?}", clip_task_id, device_rect); } // Set the global clip mask instance for this primitive. let clip_task_index = ClipTaskIndex(scratch.clip_mask_instances.len() as _); scratch.clip_mask_instances.push(ClipMaskKind::Mask(clip_task_id)); prim_info.clip_task_index = clip_task_index;
--- a/gfx/wr/webrender/src/render_task.rs +++ b/gfx/wr/webrender/src/render_task.rs @@ -521,17 +521,17 @@ impl RenderTask { root_spatial_node_index: SpatialNodeIndex, clip_store: &mut ClipStore, gpu_cache: &mut GpuCache, resource_cache: &mut ResourceCache, render_tasks: &mut RenderTaskGraph, clip_data_store: &mut ClipDataStore, device_pixel_scale: DevicePixelScale, fb_config: &FrameBuilderConfig, - ) -> Self { + ) -> RenderTaskId { // Step through the clip sources that make up this mask. If we find // any box-shadow clip sources, request that image from the render // task cache. This allows the blurred box-shadow rect to be cached // in the texture cache across frames. // TODO(gw): Consider moving this logic outside this function, especially // as we add more clip sources that depend on render tasks. // TODO(gw): If this ever shows up in a profile, we could pre-calculate // whether a ClipSources contains any box-shadows and skip @@ -558,25 +558,23 @@ impl RenderTask { kind: RenderTaskCacheKeyKind::BoxShadow(cache_key), }, gpu_cache, render_tasks, None, false, |render_tasks| { // Draw the rounded rect. - let mask_task = RenderTask::new_rounded_rect_mask( + let mask_task_id = render_tasks.add().init(RenderTask::new_rounded_rect_mask( cache_size, clip_data_address, source.minimal_shadow_rect.origin, device_pixel_scale, fb_config, - ); - - let mask_task_id = render_tasks.add(mask_task); + )); // Blur it RenderTask::new_blur( DeviceSize::new(blur_radius_dp, blur_radius_dp), mask_task_id, render_tasks, RenderTargetKind::Alpha, ClearMode::Zero, @@ -605,26 +603,28 @@ impl RenderTask { // the first (primary) clip mask will overwrite all the clip mask pixels with // blending disabled to set to the initial value. let clear_mode = if needs_clear { ClearMode::One } else { ClearMode::DontCare }; - RenderTask::with_dynamic_location( - outer_rect.size, - smallvec![], - RenderTaskKind::CacheMask(CacheMaskTask { - actual_rect: outer_rect, - clip_node_range, - root_spatial_node_index, - device_pixel_scale, - }), - clear_mode, + render_tasks.add().init( + RenderTask::with_dynamic_location( + outer_rect.size, + smallvec![], + RenderTaskKind::CacheMask(CacheMaskTask { + actual_rect: outer_rect, + clip_node_range, + root_spatial_node_index, + device_pixel_scale, + }), + clear_mode, + ) ) } pub fn new_rounded_rect_mask( size: DeviceIntSize, clip_data_address: GpuCacheAddress, local_pos: LayoutPoint, device_pixel_scale: DevicePixelScale, @@ -715,23 +715,22 @@ impl RenderTask { adjusted_blur_target_size = (blur_target_size.to_f32() / scale_factor).to_i32(); let cached_task = match blur_cache { Some(ref mut cache) => cache.get(&BlurTaskKey::DownScale(n_downscales)).cloned(), None => None, }; downscaling_src_task_id = cached_task.unwrap_or_else(|| { - let downscaling_task = RenderTask::new_scaling( + RenderTask::new_scaling( downscaling_src_task_id, render_tasks, target_kind, adjusted_blur_target_size, - ); - render_tasks.add(downscaling_task) + ) }); if let Some(ref mut cache) = blur_cache { cache.insert(BlurTaskKey::DownScale(n_downscales), downscaling_src_task_id); } n_downscales += 1; } @@ -742,45 +741,41 @@ impl RenderTask { let cached_task = match blur_cache { Some(ref mut cache) => cache.get(&blur_key).cloned(), None => None, }; let blur_region = blur_region / (scale_factor as i32); let blur_task_id = cached_task.unwrap_or_else(|| { - let blur_task_v = RenderTask::with_dynamic_location( + let blur_task_v = render_tasks.add().init(RenderTask::with_dynamic_location( adjusted_blur_target_size, smallvec![downscaling_src_task_id], RenderTaskKind::VerticalBlur(BlurTask { blur_std_deviation: adjusted_blur_std_deviation.height, target_kind, uv_rect_handle: GpuCacheHandle::new(), blur_region, uv_rect_kind, }), clear_mode, - ); - - let blur_task_v_id = render_tasks.add(blur_task_v); + )); - let blur_task_h = RenderTask::with_dynamic_location( + render_tasks.add().init(RenderTask::with_dynamic_location( adjusted_blur_target_size, - smallvec![blur_task_v_id], + smallvec![blur_task_v], RenderTaskKind::HorizontalBlur(BlurTask { blur_std_deviation: adjusted_blur_std_deviation.width, target_kind, uv_rect_handle: GpuCacheHandle::new(), blur_region, uv_rect_kind, }), clear_mode, - ); - - render_tasks.add(blur_task_h) + )) }); if let Some(ref mut cache) = blur_cache { cache.insert(blur_key, blur_task_id); } blur_task_id } @@ -799,48 +794,50 @@ impl RenderTask { ) } pub fn new_scaling( src_task_id: RenderTaskId, render_tasks: &mut RenderTaskGraph, target_kind: RenderTargetKind, size: DeviceIntSize, - ) -> Self { + ) -> RenderTaskId { Self::new_scaling_with_padding( BlitSource::RenderTask { task_id: src_task_id }, render_tasks, target_kind, size, DeviceIntSideOffsets::zero(), ) } pub fn new_scaling_with_padding( source: BlitSource, render_tasks: &mut RenderTaskGraph, target_kind: RenderTargetKind, padded_size: DeviceIntSize, padding: DeviceIntSideOffsets, - ) -> Self { + ) -> RenderTaskId { let (uv_rect_kind, children, image) = match source { BlitSource::RenderTask { task_id } => (render_tasks[task_id].uv_rect_kind(), smallvec![task_id], None), BlitSource::Image { key } => (UvRectKind::Rect, smallvec![], Some(key)), }; - RenderTask::with_dynamic_location( - padded_size, - children, - RenderTaskKind::Scaling(ScalingTask { - target_kind, - image, - uv_rect_kind, - padding, - }), - ClearMode::DontCare, + render_tasks.add().init( + RenderTask::with_dynamic_location( + padded_size, + children, + RenderTaskKind::Scaling(ScalingTask { + target_kind, + image, + uv_rect_kind, + padding, + }), + ClearMode::DontCare, + ) ) } pub fn new_svg_filter( filter_primitives: &[FilterPrimitive], filter_datas: &[SFilterData], render_tasks: &mut RenderTaskGraph, content_size: DeviceIntSize, @@ -866,32 +863,30 @@ impl RenderTask { // TODO(cbrewster): Not sure we can assume that the original input is sRGB. let (mut task_id, input_color_space) = match input.to_index(cur_index) { Some(index) => (outputs[index], filter_primitives[index].color_space), None => (original, ColorSpace::Srgb), }; match (input_color_space, color_space) { (ColorSpace::Srgb, ColorSpace::LinearRgb) => { - let task = RenderTask::new_svg_filter_primitive( + task_id = render_tasks.add().init(RenderTask::new_svg_filter_primitive( smallvec![task_id], content_size, uv_rect_kind, SvgFilterInfo::SrgbToLinear, - ); - task_id = render_tasks.add(task); + )); }, (ColorSpace::LinearRgb, ColorSpace::Srgb) => { - let task = RenderTask::new_svg_filter_primitive( + task_id = render_tasks.add().init(RenderTask::new_svg_filter_primitive( smallvec![task_id], content_size, uv_rect_kind, SvgFilterInfo::LinearToSrgb, - ); - task_id = render_tasks.add(task); + )); }, _ => {}, } task_id }; let mut outputs = vec![]; @@ -925,56 +920,53 @@ impl RenderTask { filter_primitives, render_tasks, cur_index, &outputs, original_task_id, primitive.color_space ); - let task = RenderTask::new_svg_filter_primitive( + render_tasks.add().init(RenderTask::new_svg_filter_primitive( smallvec![input_1_task_id, input_2_task_id], content_size, uv_rect_kind, SvgFilterInfo::Blend(blend.mode), - ); - render_tasks.add(task) + )) }, FilterPrimitiveKind::Flood(ref flood) => { - let task = RenderTask::new_svg_filter_primitive( + render_tasks.add().init(RenderTask::new_svg_filter_primitive( smallvec![], content_size, uv_rect_kind, SvgFilterInfo::Flood(flood.color), - ); - render_tasks.add(task) + )) } FilterPrimitiveKind::Blur(ref blur) => { let blur_std_deviation = blur.radius * device_pixel_scale.0; let input_task_id = get_task_input( &blur.input, filter_primitives, render_tasks, cur_index, &outputs, original_task_id, primitive.color_space ); - // TODO: This is a hack to ensure that a blur task's input is always in the blur's previous pass. - let svg_task = RenderTask::new_svg_filter_primitive( - smallvec![input_task_id], - content_size, - uv_rect_kind, - SvgFilterInfo::Identity, - ); - RenderTask::new_blur( DeviceSize::new(blur_std_deviation, blur_std_deviation), - render_tasks.add(svg_task), + // TODO: This is a hack to ensure that a blur task's input is always + // in the blur's previous pass. + render_tasks.add().init(RenderTask::new_svg_filter_primitive( + smallvec![input_task_id], + content_size, + uv_rect_kind, + SvgFilterInfo::Identity, + )), render_tasks, RenderTargetKind::Color, ClearMode::Transparent, None, content_size, ) } FilterPrimitiveKind::Opacity(ref opacity) => { @@ -983,82 +975,80 @@ impl RenderTask { filter_primitives, render_tasks, cur_index, &outputs, original_task_id, primitive.color_space ); - let task = RenderTask::new_svg_filter_primitive( + render_tasks.add().init(RenderTask::new_svg_filter_primitive( smallvec![input_task_id], content_size, uv_rect_kind, SvgFilterInfo::Opacity(opacity.opacity), - ); - render_tasks.add(task) + )) } FilterPrimitiveKind::ColorMatrix(ref color_matrix) => { let input_task_id = get_task_input( &color_matrix.input, filter_primitives, render_tasks, cur_index, &outputs, original_task_id, primitive.color_space ); - let task = RenderTask::new_svg_filter_primitive( + render_tasks.add().init(RenderTask::new_svg_filter_primitive( smallvec![input_task_id], content_size, uv_rect_kind, SvgFilterInfo::ColorMatrix(Box::new(color_matrix.matrix)), - ); - render_tasks.add(task) + )) } FilterPrimitiveKind::DropShadow(ref drop_shadow) => { let input_task_id = get_task_input( &drop_shadow.input, filter_primitives, render_tasks, cur_index, &outputs, original_task_id, primitive.color_space ); let blur_std_deviation = drop_shadow.shadow.blur_radius * device_pixel_scale.0; let offset = drop_shadow.shadow.offset * LayoutToWorldScale::new(1.0) * device_pixel_scale; - let offset_task = RenderTask::new_svg_filter_primitive( - smallvec![input_task_id], - content_size, - uv_rect_kind, - SvgFilterInfo::Offset(offset), + let offset_task_id = render_tasks.add().init( + RenderTask::new_svg_filter_primitive( + smallvec![input_task_id], + content_size, + uv_rect_kind, + SvgFilterInfo::Offset(offset), + ) ); - let offset_task_id = render_tasks.add(offset_task); let blur_task_id = RenderTask::new_blur( DeviceSize::new(blur_std_deviation, blur_std_deviation), offset_task_id, render_tasks, RenderTargetKind::Color, ClearMode::Transparent, None, content_size, ); - let task = RenderTask::new_svg_filter_primitive( + render_tasks.add().init(RenderTask::new_svg_filter_primitive( smallvec![input_task_id, blur_task_id], content_size, uv_rect_kind, SvgFilterInfo::DropShadow(drop_shadow.shadow.color), - ); - render_tasks.add(task) + )) } FilterPrimitiveKind::ComponentTransfer(ref component_transfer) => { let input_task_id = get_task_input( &component_transfer.input, filter_primitives, render_tasks, cur_index, &outputs, @@ -1066,44 +1056,42 @@ impl RenderTask { primitive.color_space ); let filter_data = &filter_datas[cur_filter_data]; cur_filter_data += 1; if filter_data.is_identity() { input_task_id } else { - let task = RenderTask::new_svg_filter_primitive( + render_tasks.add().init(RenderTask::new_svg_filter_primitive( smallvec![input_task_id], content_size, uv_rect_kind, SvgFilterInfo::ComponentTransfer(filter_data.clone()), - ); - render_tasks.add(task) + )) } } FilterPrimitiveKind::Offset(ref info) => { let input_task_id = get_task_input( &info.input, filter_primitives, render_tasks, cur_index, &outputs, original_task_id, primitive.color_space ); let offset = info.offset * LayoutToWorldScale::new(1.0) * device_pixel_scale; - let offset_task = RenderTask::new_svg_filter_primitive( + render_tasks.add().init(RenderTask::new_svg_filter_primitive( smallvec![input_task_id], content_size, uv_rect_kind, SvgFilterInfo::Offset(offset), - ); - render_tasks.add(offset_task) + )) } FilterPrimitiveKind::Composite(info) => { let input_1_task_id = get_task_input( &info.input1, filter_primitives, render_tasks, cur_index, &outputs, @@ -1115,40 +1103,38 @@ impl RenderTask { filter_primitives, render_tasks, cur_index, &outputs, original_task_id, primitive.color_space ); - let task = RenderTask::new_svg_filter_primitive( + render_tasks.add().init(RenderTask::new_svg_filter_primitive( smallvec![input_1_task_id, input_2_task_id], content_size, uv_rect_kind, SvgFilterInfo::Composite(info.operator), - ); - render_tasks.add(task) + )) } }; outputs.push(render_task_id); } // The output of a filter is the output of the last primitive in the chain. let mut render_task_id = *outputs.last().unwrap(); // Convert to sRGB if needed if filter_primitives.last().unwrap().color_space == ColorSpace::LinearRgb { - let task = RenderTask::new_svg_filter_primitive( + render_task_id = render_tasks.add().init(RenderTask::new_svg_filter_primitive( smallvec![render_task_id], content_size, uv_rect_kind, SvgFilterInfo::LinearToSrgb, - ); - render_task_id = render_tasks.add(task); + )); } render_task_id } pub fn new_svg_filter_primitive( tasks: TaskDependencies, target_size: DeviceIntSize, @@ -1553,16 +1539,17 @@ impl RenderTask { } } pt.end_level(); true } /// Mark this render task for keeping the results alive up until the end of the frame. + #[inline] pub fn mark_for_saving(&mut self) { match self.location { RenderTaskLocation::Fixed(..) | RenderTaskLocation::Dynamic(..) => { self.saved_index = Some(SavedTargetIndex::PENDING); } RenderTaskLocation::TextureCache { .. } | RenderTaskLocation::PictureCache { .. } => {
--- a/gfx/wr/webrender/src/render_task_graph.rs +++ b/gfx/wr/webrender/src/render_task_graph.rs @@ -6,32 +6,55 @@ use api::ImageFormat; use api::units::*; use crate::internal_types::{CacheTextureId, FastHashMap, SavedTargetIndex}; use crate::render_backend::FrameId; use crate::render_target::{RenderTarget, RenderTargetKind, RenderTargetList, ColorRenderTarget}; use crate::render_target::{PictureCacheTarget, TextureCacheRenderTarget, AlphaRenderTarget}; use crate::render_task::{BlitSource, RenderTask, RenderTaskKind, RenderTaskAddress, RenderTaskData}; use crate::render_task::{RenderTaskLocation}; +use crate::util::{VecHelper, Allocation}; use std::{cmp, usize, f32, i32, u32}; #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct RenderTaskGraph { pub tasks: Vec<RenderTask>, pub task_data: Vec<RenderTaskData>, /// Tasks that don't have dependencies, and that may be shared between /// picture tasks. /// /// We render these unconditionally before-rendering the rest of the tree. pub cacheable_render_tasks: Vec<RenderTaskId>, next_saved: SavedTargetIndex, frame_id: FrameId, } +/// Allows initializing a render task directly into the render task buffer. +/// +/// See utils::VecHelpers. RenderTask is fairly large so avoiding the move when +/// pushing into the vector can save a lot of exensive memcpys on pages with many +/// render tasks. +pub struct RenderTaskAllocation<'a> { + alloc: Allocation<'a, RenderTask>, + #[cfg(debug_assertions)] + frame_id: FrameId, +} + +impl<'l> RenderTaskAllocation<'l> { + #[inline(always)] + pub fn init(self, value: RenderTask) -> RenderTaskId { + RenderTaskId { + index: self.alloc.init(value) as u32, + #[cfg(debug_assertions)] + frame_id: self.frame_id, + } + } +} + impl RenderTaskGraph { pub fn new(frame_id: FrameId, counters: &RenderTaskGraphCounters) -> Self { // Preallocate a little more than what we needed in the previous frame so that small variations // in the number of items don't cause us to constantly reallocate. let extra_items = 8; RenderTaskGraph { tasks: Vec::with_capacity(counters.tasks_len + extra_items), task_data: Vec::with_capacity(counters.task_data_len + extra_items), @@ -44,21 +67,19 @@ impl RenderTaskGraph { pub fn counters(&self) -> RenderTaskGraphCounters { RenderTaskGraphCounters { tasks_len: self.tasks.len(), task_data_len: self.task_data.len(), cacheable_render_tasks_len: self.cacheable_render_tasks.len(), } } - pub fn add(&mut self, task: RenderTask) -> RenderTaskId { - let index = self.tasks.len() as _; - self.tasks.push(task); - RenderTaskId { - index, + pub fn add(&mut self) -> RenderTaskAllocation { + RenderTaskAllocation { + alloc: self.tasks.alloc(), #[cfg(debug_assertions)] frame_id: self.frame_id, } } /// Express a render task dependency between a parent and child task. /// This is used to assign tasks to render passes. pub fn add_dependency( @@ -169,23 +190,23 @@ impl RenderTaskGraph { &mut max_depth, ); } let offset = passes.len(); passes.reserve(max_depth as usize + 1); for _ in 0..max_depth { - passes.push(RenderPass::new_off_screen(screen_size, gpu_supports_fast_clears)); + passes.alloc().init(RenderPass::new_off_screen(screen_size, gpu_supports_fast_clears)); } if for_main_framebuffer { - passes.push(RenderPass::new_main_framebuffer(screen_size, gpu_supports_fast_clears)); + passes.alloc().init(RenderPass::new_main_framebuffer(screen_size, gpu_supports_fast_clears)); } else { - passes.push(RenderPass::new_off_screen(screen_size, gpu_supports_fast_clears)); + passes.alloc().init(RenderPass::new_off_screen(screen_size, gpu_supports_fast_clears)); } // Assign tasks to their render passes. for task_index in 0..self.tasks.len() { if task_max_depths[task_index] < 0 { // The task wasn't visited, it means it doesn't contribute to this frame. continue; } @@ -310,17 +331,17 @@ impl RenderTaskGraph { } let blit_id = RenderTaskId { index: self.tasks.len() as u32, #[cfg(debug_assertions)] frame_id: self.frame_id, }; - self.tasks.push(blit); + self.tasks.alloc().init(blit); passes[child_pass_index as usize + 1].tasks.push(blit_id); self.tasks[task_index].children[nth_child] = blit_id; task_redirects[child_task_index] = Some(blit_id); } } } @@ -710,21 +731,21 @@ fn diamond_task_graph() { // \ / // [b2] let color = RenderTargetKind::Color; let counters = RenderTaskGraphCounters::new(); let mut tasks = RenderTaskGraph::new(FrameId::first(), &counters); - let a = tasks.add(RenderTask::new_test(color, dyn_location(640, 640), SmallVec::new())); - let b1 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), smallvec![a])); - let b2 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), smallvec![a])); + let a = tasks.add().init(RenderTask::new_test(color, dyn_location(640, 640), SmallVec::new())); + let b1 = tasks.add().init(RenderTask::new_test(color, dyn_location(320, 320), smallvec![a])); + let b2 = tasks.add().init(RenderTask::new_test(color, dyn_location(320, 320), smallvec![a])); - let main_pic = tasks.add(RenderTask::new_test( + let main_pic = tasks.add().init(RenderTask::new_test( color, RenderTaskLocation::Fixed(rect(0, 0, 3200, 1800)), smallvec![b1, b2], )); let initial_number_of_tasks = tasks.tasks.len(); let passes = tasks.generate_passes(Some(main_pic), size2(3200, 1800), true); @@ -747,41 +768,41 @@ fn blur_task_graph() { // This test simulates a complicated shadow stack effect with target allocation // conflicts to resolve. let color = RenderTargetKind::Color; let counters = RenderTaskGraphCounters::new(); let mut tasks = RenderTaskGraph::new(FrameId::first(), &counters); - let pic = tasks.add(RenderTask::new_test(color, dyn_location(640, 640), SmallVec::new())); - let scale1 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), smallvec![pic])); - let scale2 = tasks.add(RenderTask::new_test(color, dyn_location(160, 160), smallvec![scale1])); - let scale3 = tasks.add(RenderTask::new_test(color, dyn_location(80, 80), smallvec![scale2])); - let scale4 = tasks.add(RenderTask::new_test(color, dyn_location(40, 40), smallvec![scale3])); + let pic = tasks.add().init(RenderTask::new_test(color, dyn_location(640, 640), SmallVec::new())); + let scale1 = tasks.add().init(RenderTask::new_test(color, dyn_location(320, 320), smallvec![pic])); + let scale2 = tasks.add().init(RenderTask::new_test(color, dyn_location(160, 160), smallvec![scale1])); + let scale3 = tasks.add().init(RenderTask::new_test(color, dyn_location(80, 80), smallvec![scale2])); + let scale4 = tasks.add().init(RenderTask::new_test(color, dyn_location(40, 40), smallvec![scale3])); - let vblur1 = tasks.add(RenderTask::new_test(color, dyn_location(40, 40), smallvec![scale4])); - let hblur1 = tasks.add(RenderTask::new_test(color, dyn_location(40, 40), smallvec![vblur1])); + let vblur1 = tasks.add().init(RenderTask::new_test(color, dyn_location(40, 40), smallvec![scale4])); + let hblur1 = tasks.add().init(RenderTask::new_test(color, dyn_location(40, 40), smallvec![vblur1])); - let vblur2 = tasks.add(RenderTask::new_test(color, dyn_location(40, 40), smallvec![scale4])); - let hblur2 = tasks.add(RenderTask::new_test(color, dyn_location(40, 40), smallvec![vblur2])); + let vblur2 = tasks.add().init(RenderTask::new_test(color, dyn_location(40, 40), smallvec![scale4])); + let hblur2 = tasks.add().init(RenderTask::new_test(color, dyn_location(40, 40), smallvec![vblur2])); // Insert a task that is an even number of passes away from its dependency. // This means the source and destination are on the same target and we have to resolve // this conflict by automatically inserting a blit task. - let vblur3 = tasks.add(RenderTask::new_test(color, dyn_location(80, 80), smallvec![scale3])); - let hblur3 = tasks.add(RenderTask::new_test(color, dyn_location(80, 80), smallvec![vblur3])); + let vblur3 = tasks.add().init(RenderTask::new_test(color, dyn_location(80, 80), smallvec![scale3])); + let hblur3 = tasks.add().init(RenderTask::new_test(color, dyn_location(80, 80), smallvec![vblur3])); // Insert a task that is an odd number > 1 of passes away from its dependency. // This should force us to mark the dependency "for saving" to keep its content valid // until the task can access it. - let vblur4 = tasks.add(RenderTask::new_test(color, dyn_location(160, 160), smallvec![scale2])); - let hblur4 = tasks.add(RenderTask::new_test(color, dyn_location(160, 160), smallvec![vblur4])); + let vblur4 = tasks.add().init(RenderTask::new_test(color, dyn_location(160, 160), smallvec![scale2])); + let hblur4 = tasks.add().init(RenderTask::new_test(color, dyn_location(160, 160), smallvec![vblur4])); - let main_pic = tasks.add(RenderTask::new_test( + let main_pic = tasks.add().init(RenderTask::new_test( color, RenderTaskLocation::Fixed(rect(0, 0, 3200, 1800)), smallvec![hblur1, hblur2, hblur3, hblur4], )); let initial_number_of_tasks = tasks.tasks.len(); let passes = tasks.generate_passes(Some(main_pic), size2(3200, 1800), true); @@ -832,24 +853,24 @@ fn culled_tasks() { // This test checks that tasks that do not contribute to the frame don't appear in the // generated passes. let color = RenderTargetKind::Color; let counters = RenderTaskGraphCounters::new(); let mut tasks = RenderTaskGraph::new(FrameId::first(), &counters); - let a1 = tasks.add(RenderTask::new_test(color, dyn_location(640, 640), SmallVec::new())); - let _a2 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), smallvec![a1])); + let a1 = tasks.add().init(RenderTask::new_test(color, dyn_location(640, 640), SmallVec::new())); + let _a2 = tasks.add().init(RenderTask::new_test(color, dyn_location(320, 320), smallvec![a1])); - let b1 = tasks.add(RenderTask::new_test(color, dyn_location(640, 640), SmallVec::new())); - let b2 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), smallvec![b1])); - let _b3 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), smallvec![b2])); + let b1 = tasks.add().init(RenderTask::new_test(color, dyn_location(640, 640), SmallVec::new())); + let b2 = tasks.add().init(RenderTask::new_test(color, dyn_location(320, 320), smallvec![b1])); + let _b3 = tasks.add().init(RenderTask::new_test(color, dyn_location(320, 320), smallvec![b2])); - let main_pic = tasks.add(RenderTask::new_test( + let main_pic = tasks.add().init(RenderTask::new_test( color, RenderTaskLocation::Fixed(rect(0, 0, 3200, 1800)), smallvec![b2], )); let initial_number_of_tasks = tasks.tasks.len(); let passes = tasks.generate_passes(Some(main_pic), size2(3200, 1800), true);