зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1611176 - Avoid expensive memmoves when adding render tasks. r=gw
On pages with many render tasks (typically a lot of text shadows), we spend a lot of time moving RenderTask which is a fairly large struct into the render graph's buffer. This patch avoids it by using the VecHelper trick of allocaitng space before initializing the value. Some RenderTask::new_* methods which take the render task graph in parameter were modified to add the task and return the task ID to work around borrow-checking restriction. Differential Revision: https://phabricator.services.mozilla.com/D60854 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
6836a4dde4
Коммит
ea36628e1e
|
@ -270,20 +270,20 @@ impl FrameBuilder {
|
|||
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(
|
||||
|
|
|
@ -3755,20 +3755,20 @@ impl PicturePrimitive {
|
|||
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,
|
||||
|
@ -3818,20 +3818,22 @@ impl PicturePrimitive {
|
|||
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().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();
|
||||
|
||||
let picture_task_id = frame_state.render_tasks.add(picture_task);
|
||||
picture_task
|
||||
});
|
||||
|
||||
self.secondary_render_task_id = Some(picture_task_id);
|
||||
|
||||
|
@ -3865,19 +3867,7 @@ impl PicturePrimitive {
|
|||
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)
|
||||
);
|
||||
|
||||
|
@ -3888,7 +3878,19 @@ impl PicturePrimitive {
|
|||
|
||||
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))
|
||||
}
|
||||
|
@ -3901,20 +3903,20 @@ impl PicturePrimitive {
|
|||
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(..) => {
|
||||
|
@ -3926,20 +3928,20 @@ impl PicturePrimitive {
|
|||
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 { .. } => {
|
||||
|
@ -4138,23 +4140,23 @@ impl PicturePrimitive {
|
|||
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,
|
||||
|
@ -4202,20 +4204,20 @@ impl PicturePrimitive {
|
|||
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) => {
|
||||
|
@ -4227,20 +4229,20 @@ impl PicturePrimitive {
|
|||
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,
|
||||
|
|
|
@ -237,35 +237,24 @@ impl ImageData {
|
|||
// 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)
|
||||
))
|
||||
}
|
||||
));
|
||||
}
|
||||
|
|
|
@ -1063,7 +1063,7 @@ impl BrushSegment {
|
|||
}
|
||||
};
|
||||
|
||||
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,
|
||||
|
@ -1075,8 +1075,6 @@ impl BrushSegment {
|
|||
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
|
||||
|
@ -2903,14 +2901,13 @@ impl PrimitiveStore {
|
|||
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)
|
||||
))
|
||||
}
|
||||
));
|
||||
}
|
||||
|
@ -3025,7 +3022,7 @@ impl PrimitiveStore {
|
|||
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,
|
||||
|
@ -3033,9 +3030,7 @@ impl PrimitiveStore {
|
|||
&border_data.border,
|
||||
scale,
|
||||
),
|
||||
);
|
||||
|
||||
render_tasks.add(task)
|
||||
))
|
||||
}
|
||||
));
|
||||
}
|
||||
|
@ -3207,15 +3202,13 @@ impl PrimitiveStore {
|
|||
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)
|
||||
))
|
||||
}
|
||||
));
|
||||
}
|
||||
|
@ -4024,7 +4017,7 @@ impl PrimitiveInstance {
|
|||
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,
|
||||
|
@ -4036,8 +4029,6 @@ impl PrimitiveInstance {
|
|||
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);
|
||||
|
|
|
@ -526,7 +526,7 @@ impl RenderTask {
|
|||
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
|
||||
|
@ -563,15 +563,13 @@ impl RenderTask {
|
|||
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(
|
||||
|
@ -610,16 +608,18 @@ impl RenderTask {
|
|||
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,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -720,13 +720,12 @@ impl RenderTask {
|
|||
};
|
||||
|
||||
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 {
|
||||
|
@ -747,7 +746,7 @@ impl RenderTask {
|
|||
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 {
|
||||
|
@ -758,13 +757,11 @@ impl RenderTask {
|
|||
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,
|
||||
|
@ -773,9 +770,7 @@ impl RenderTask {
|
|||
uv_rect_kind,
|
||||
}),
|
||||
clear_mode,
|
||||
);
|
||||
|
||||
render_tasks.add(blur_task_h)
|
||||
))
|
||||
});
|
||||
|
||||
if let Some(ref mut cache) = blur_cache {
|
||||
|
@ -804,7 +799,7 @@ impl RenderTask {
|
|||
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,
|
||||
|
@ -820,22 +815,24 @@ impl RenderTask {
|
|||
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,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -871,22 +868,20 @@ impl RenderTask {
|
|||
|
||||
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);
|
||||
));
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
@ -930,22 +925,20 @@ impl RenderTask {
|
|||
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;
|
||||
|
@ -959,17 +952,16 @@ impl RenderTask {
|
|||
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,
|
||||
|
@ -988,13 +980,12 @@ impl RenderTask {
|
|||
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(
|
||||
|
@ -1007,13 +998,12 @@ impl RenderTask {
|
|||
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(
|
||||
|
@ -1029,13 +1019,14 @@ impl RenderTask {
|
|||
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),
|
||||
|
@ -1047,13 +1038,12 @@ impl RenderTask {
|
|||
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(
|
||||
|
@ -1071,13 +1061,12 @@ impl RenderTask {
|
|||
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) => {
|
||||
|
@ -1092,13 +1081,12 @@ impl RenderTask {
|
|||
);
|
||||
|
||||
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(
|
||||
|
@ -1120,13 +1108,12 @@ impl RenderTask {
|
|||
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);
|
||||
|
@ -1137,13 +1124,12 @@ impl RenderTask {
|
|||
|
||||
// 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
|
||||
|
@ -1558,6 +1544,7 @@ impl RenderTask {
|
|||
}
|
||||
|
||||
/// 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(..) |
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::render_target::{RenderTarget, RenderTargetKind, RenderTargetList, Col
|
|||
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))]
|
||||
|
@ -27,6 +28,28 @@ pub struct RenderTaskGraph {
|
|||
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
|
||||
|
@ -49,11 +72,9 @@ impl RenderTaskGraph {
|
|||
}
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
@ -174,13 +195,13 @@ impl RenderTaskGraph {
|
|||
|
||||
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.
|
||||
|
@ -315,7 +336,7 @@ impl RenderTaskGraph {
|
|||
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);
|
||||
|
||||
|
@ -715,11 +736,11 @@ fn diamond_task_graph() {
|
|||
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],
|
||||
|
@ -752,31 +773,31 @@ fn blur_task_graph() {
|
|||
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],
|
||||
|
@ -837,14 +858,14 @@ fn culled_tasks() {
|
|||
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],
|
||||
|
|
Загрузка…
Ссылка в новой задаче