Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync changes from mozilla-central gfx/wr #3838

Merged
merged 2 commits into from Jan 21, 2020
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

Bug 1607836 - use SmallVec for render task dependencies. r=gw

The majority of render tasks have 0, 1 or 2 dependencies, except for pictures that typically have dozens to hundreds of dependencies. SmallVec with 2 inline elements avoids many tiny heap allocations in pages with a lot of text shadows and other types of render tasks.

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

[ghsync] From https://hg.mozilla.org/mozilla-central/rev/db0378df4c6616330779c46cd830dd2f76f53b1b
  • Loading branch information
nical authored and moz-gfx committed Jan 21, 2020
commit 7f657546a1f168548bf4d13148a47a7d8da6e4a8
@@ -23,6 +23,7 @@ use std::{usize, f32, i32, u32};
use crate::render_target::{RenderTargetIndex, RenderTargetKind};
use crate::render_task_graph::{RenderTaskGraph, RenderTaskId};
use crate::render_task_cache::{RenderTaskCacheKey, RenderTaskCacheKeyKind};
use smallvec::SmallVec;

const RENDER_TASK_SIZE_SANITY_CHECK: i32 = 16000;
const FLOATS_PER_RENDER_TASK_INFO: usize = 8;
@@ -340,11 +341,17 @@ impl BlurTaskKey {
}
}

// The majority of render tasks have 0, 1 or 2 dependencies, except for pictures that
// typically have dozens to hundreds of dependencies. SmallVec with 2 inline elements
// avoids many tiny heap allocations in pages with a lot of text shadows and other
// types of render tasks.
pub type TaskDependencies = SmallVec<[RenderTaskId;2]>;

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct RenderTask {
pub location: RenderTaskLocation,
pub children: Vec<RenderTaskId>,
pub children: TaskDependencies,
pub kind: RenderTaskKind,
pub clear_mode: ClearMode,
pub saved_index: Option<SavedTargetIndex>,
@@ -354,7 +361,7 @@ impl RenderTask {
#[inline]
pub fn with_dynamic_location(
size: DeviceIntSize,
children: Vec<RenderTaskId>,
children: TaskDependencies,
kind: RenderTaskKind,
clear_mode: ClearMode,
) -> Self {
@@ -373,7 +380,7 @@ impl RenderTask {
pub fn new_test(
target: RenderTargetKind,
location: RenderTaskLocation,
children: Vec<RenderTaskId>,
children: TaskDependencies,
) -> Self {
RenderTask {
location,
@@ -409,7 +416,7 @@ impl RenderTask {

RenderTask {
location,
children: Vec::new(),
children: TaskDependencies::new(),
kind: RenderTaskKind::Picture(PictureTask {
pic_index,
content_origin,
@@ -435,7 +442,7 @@ impl RenderTask {
) -> Self {
RenderTask::with_dynamic_location(
size,
Vec::new(),
TaskDependencies::new(),
RenderTaskKind::Gradient(GradientTask {
stops,
orientation,
@@ -449,7 +456,7 @@ impl RenderTask {
pub fn new_readback(screen_rect: DeviceIntRect) -> Self {
RenderTask::with_dynamic_location(
screen_rect.size,
Vec::new(),
TaskDependencies::new(),
RenderTaskKind::Readback(screen_rect),
ClearMode::Transparent,
)
@@ -473,8 +480,8 @@ impl RenderTask {
// and made available as an input when this task
// executes.
let children = match source {
BlitSource::RenderTask { task_id } => vec![task_id],
BlitSource::Image { .. } => vec![],
BlitSource::RenderTask { task_id } => smallvec![task_id],
BlitSource::Image { .. } => smallvec![],
};

RenderTask::with_dynamic_location(
@@ -497,7 +504,7 @@ impl RenderTask {
) -> Self {
RenderTask::with_dynamic_location(
size,
Vec::new(),
TaskDependencies::new(),
RenderTaskKind::LineDecoration(LineDecorationTask {
style,
orientation,
@@ -605,7 +612,7 @@ impl RenderTask {

RenderTask::with_dynamic_location(
outer_rect.size,
vec![],
smallvec![],
RenderTaskKind::CacheMask(CacheMaskTask {
actual_rect: outer_rect,
clip_node_range,
@@ -631,7 +638,7 @@ impl RenderTask {

RenderTask::with_dynamic_location(
size,
Vec::new(),
TaskDependencies::new(),
RenderTaskKind::ClipRegion(ClipRegionTask {
clip_data_address,
local_pos,
@@ -742,7 +749,7 @@ impl RenderTask {
let blur_task_id = cached_task.unwrap_or_else(|| {
let blur_task_v = RenderTask::with_dynamic_location(
adjusted_blur_target_size,
vec![downscaling_src_task_id],
smallvec![downscaling_src_task_id],
RenderTaskKind::VerticalBlur(BlurTask {
blur_std_deviation: adjusted_blur_std_deviation.height,
target_kind,
@@ -757,7 +764,7 @@ impl RenderTask {

let blur_task_h = RenderTask::with_dynamic_location(
adjusted_blur_target_size,
vec![blur_task_v_id],
smallvec![blur_task_v_id],
RenderTaskKind::HorizontalBlur(BlurTask {
blur_std_deviation: adjusted_blur_std_deviation.width,
target_kind,
@@ -784,7 +791,7 @@ impl RenderTask {
) -> Self {
RenderTask::with_dynamic_location(
size,
Vec::new(),
TaskDependencies::new(),
RenderTaskKind::Border(BorderTask {
instances,
}),
@@ -815,8 +822,8 @@ impl RenderTask {
padding: DeviceIntSideOffsets,
) -> Self {
let (uv_rect_kind, children, image) = match source {
BlitSource::RenderTask { task_id } => (render_tasks[task_id].uv_rect_kind(), vec![task_id], None),
BlitSource::Image { key } => (UvRectKind::Rect, vec![], Some(key)),
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(
@@ -865,7 +872,7 @@ impl RenderTask {
match (input_color_space, color_space) {
(ColorSpace::Srgb, ColorSpace::LinearRgb) => {
let task = RenderTask::new_svg_filter_primitive(
vec![task_id],
smallvec![task_id],
content_size,
uv_rect_kind,
SvgFilterInfo::SrgbToLinear,
@@ -874,7 +881,7 @@ impl RenderTask {
},
(ColorSpace::LinearRgb, ColorSpace::Srgb) => {
let task = RenderTask::new_svg_filter_primitive(
vec![task_id],
smallvec![task_id],
content_size,
uv_rect_kind,
SvgFilterInfo::LinearToSrgb,
@@ -924,7 +931,7 @@ impl RenderTask {
);

let task = RenderTask::new_svg_filter_primitive(
vec![input_1_task_id, input_2_task_id],
smallvec![input_1_task_id, input_2_task_id],
content_size,
uv_rect_kind,
SvgFilterInfo::Blend(blend.mode),
@@ -933,7 +940,7 @@ impl RenderTask {
},
FilterPrimitiveKind::Flood(ref flood) => {
let task = RenderTask::new_svg_filter_primitive(
vec![],
smallvec![],
content_size,
uv_rect_kind,
SvgFilterInfo::Flood(flood.color),
@@ -954,7 +961,7 @@ impl RenderTask {

// 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(
vec![input_task_id],
smallvec![input_task_id],
content_size,
uv_rect_kind,
SvgFilterInfo::Identity,
@@ -982,7 +989,7 @@ impl RenderTask {
);

let task = RenderTask::new_svg_filter_primitive(
vec![input_task_id],
smallvec![input_task_id],
content_size,
uv_rect_kind,
SvgFilterInfo::Opacity(opacity.opacity),
@@ -1001,7 +1008,7 @@ impl RenderTask {
);

let task = RenderTask::new_svg_filter_primitive(
vec![input_task_id],
smallvec![input_task_id],
content_size,
uv_rect_kind,
SvgFilterInfo::ColorMatrix(Box::new(color_matrix.matrix)),
@@ -1023,7 +1030,7 @@ impl RenderTask {
let offset = drop_shadow.shadow.offset * LayoutToWorldScale::new(1.0) * device_pixel_scale;

let offset_task = RenderTask::new_svg_filter_primitive(
vec![input_task_id],
smallvec![input_task_id],
content_size,
uv_rect_kind,
SvgFilterInfo::Offset(offset),
@@ -1041,7 +1048,7 @@ impl RenderTask {
);

let task = RenderTask::new_svg_filter_primitive(
vec![input_task_id, blur_task_id],
smallvec![input_task_id, blur_task_id],
content_size,
uv_rect_kind,
SvgFilterInfo::DropShadow(drop_shadow.shadow.color),
@@ -1065,7 +1072,7 @@ impl RenderTask {
input_task_id
} else {
let task = RenderTask::new_svg_filter_primitive(
vec![input_task_id],
smallvec![input_task_id],
content_size,
uv_rect_kind,
SvgFilterInfo::ComponentTransfer(filter_data.clone()),
@@ -1086,7 +1093,7 @@ impl RenderTask {

let offset = info.offset * LayoutToWorldScale::new(1.0) * device_pixel_scale;
let offset_task = RenderTask::new_svg_filter_primitive(
vec![input_task_id],
smallvec![input_task_id],
content_size,
uv_rect_kind,
SvgFilterInfo::Offset(offset),
@@ -1114,7 +1121,7 @@ impl RenderTask {
);

let task = RenderTask::new_svg_filter_primitive(
vec![input_1_task_id, input_2_task_id],
smallvec![input_1_task_id, input_2_task_id],
content_size,
uv_rect_kind,
SvgFilterInfo::Composite(info.operator),
@@ -1131,7 +1138,7 @@ impl RenderTask {
// Convert to sRGB if needed
if filter_primitives.last().unwrap().color_space == ColorSpace::LinearRgb {
let task = RenderTask::new_svg_filter_primitive(
vec![render_task_id],
smallvec![render_task_id],
content_size,
uv_rect_kind,
SvgFilterInfo::LinearToSrgb,
@@ -1143,7 +1150,7 @@ impl RenderTask {
}

pub fn new_svg_filter_primitive(
tasks: Vec<RenderTaskId>,
tasks: TaskDependencies,
target_size: DeviceIntSize,
uv_rect_kind: UvRectKind,
info: SvgFilterInfo,
@@ -692,6 +692,8 @@ fn dump_task_dependency_link(

#[cfg(test)]
use euclid::{size2, rect};
#[cfg(test)]
use smallvec::SmallVec;

#[cfg(test)]
fn dyn_location(w: i32, h: i32) -> RenderTaskLocation {
@@ -713,14 +715,14 @@ 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), Vec::new()));
let b1 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), vec![a]));
let b2 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), vec![a]));
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 main_pic = tasks.add(RenderTask::new_test(
color,
RenderTaskLocation::Fixed(rect(0, 0, 3200, 1800)),
vec![b1, b2],
smallvec![b1, b2],
));

let initial_number_of_tasks = tasks.tasks.len();
@@ -750,34 +752,34 @@ 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), Vec::new()));
let scale1 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), vec![pic]));
let scale2 = tasks.add(RenderTask::new_test(color, dyn_location(160, 160), vec![scale1]));
let scale3 = tasks.add(RenderTask::new_test(color, dyn_location(80, 80), vec![scale2]));
let scale4 = tasks.add(RenderTask::new_test(color, dyn_location(40, 40), vec![scale3]));
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 vblur1 = tasks.add(RenderTask::new_test(color, dyn_location(40, 40), vec![scale4]));
let hblur1 = tasks.add(RenderTask::new_test(color, dyn_location(40, 40), vec![vblur1]));
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 vblur2 = tasks.add(RenderTask::new_test(color, dyn_location(40, 40), vec![scale4]));
let hblur2 = tasks.add(RenderTask::new_test(color, dyn_location(40, 40), vec![vblur2]));
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]));

// 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), vec![scale3]));
let hblur3 = tasks.add(RenderTask::new_test(color, dyn_location(80, 80), vec![vblur3]));
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]));

// 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), vec![scale2]));
let hblur4 = tasks.add(RenderTask::new_test(color, dyn_location(160, 160), vec![vblur4]));
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 main_pic = tasks.add(RenderTask::new_test(
color,
RenderTaskLocation::Fixed(rect(0, 0, 3200, 1800)),
vec![hblur1, hblur2, hblur3, hblur4],
smallvec![hblur1, hblur2, hblur3, hblur4],
));

let initial_number_of_tasks = tasks.tasks.len();
@@ -835,17 +837,17 @@ 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), Vec::new()));
let _a2 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), vec![a1]));
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 b1 = tasks.add(RenderTask::new_test(color, dyn_location(640, 640), Vec::new()));
let b2 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), vec![b1]));
let _b3 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), vec![b2]));
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 main_pic = tasks.add(RenderTask::new_test(
color,
RenderTaskLocation::Fixed(rect(0, 0, 3200, 1800)),
vec![b2],
smallvec![b2],
));

let initial_number_of_tasks = tasks.tasks.len();
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.