Skip to content

Commit 83b830f

Browse files
committed
Avoid picture primitive copies via VecHelper
1 parent 586af96 commit 83b830f

File tree

4 files changed

+154
-123
lines changed

4 files changed

+154
-123
lines changed

webrender/src/display_list_flattener.rs

+108-108
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use spatial_node::{StickyFrameInfo};
3434
use std::{f32, mem};
3535
use std::collections::vec_deque::VecDeque;
3636
use tiling::{CompositeOps};
37-
use util::{MaxRect};
37+
use util::{MaxRect, VecHelper};
3838

3939
#[derive(Debug, Copy, Clone)]
4040
struct ClipNode {
@@ -1114,23 +1114,24 @@ impl<'a> DisplayListFlattener<'a> {
11141114
};
11151115

11161116
// Add picture for this actual stacking context contents to render into.
1117-
let prim_list = PrimitiveList::new(
1118-
stacking_context.primitives,
1119-
&self.resources.prim_interner,
1120-
);
1121-
let leaf_picture = PicturePrimitive::new_image(
1122-
leaf_composite_mode,
1123-
leaf_context_3d,
1124-
stacking_context.pipeline_id,
1125-
leaf_output_pipeline_id,
1126-
true,
1127-
stacking_context.requested_raster_space,
1128-
prim_list,
1129-
stacking_context.spatial_node_index,
1130-
max_clip,
1131-
&self.clip_store,
1117+
let leaf_pic_index = PictureIndex(self.prim_store.pictures
1118+
.alloc()
1119+
.init(PicturePrimitive::new_image(
1120+
leaf_composite_mode,
1121+
leaf_context_3d,
1122+
stacking_context.pipeline_id,
1123+
leaf_output_pipeline_id,
1124+
true,
1125+
stacking_context.requested_raster_space,
1126+
PrimitiveList::new(
1127+
stacking_context.primitives,
1128+
&self.resources.prim_interner,
1129+
),
1130+
stacking_context.spatial_node_index,
1131+
max_clip,
1132+
&self.clip_store,
1133+
))
11321134
);
1133-
let leaf_pic_index = self.prim_store.create_picture(leaf_picture);
11341135

11351136
// Create a chain of pictures based on presence of filters,
11361137
// mix-blend-mode and/or 3d rendering context containers.
@@ -1153,56 +1154,56 @@ impl<'a> DisplayListFlattener<'a> {
11531154
if let Picture3DContext::In { root_data: Some(mut prims), ancestor_index } = stacking_context.context_3d {
11541155
prims.push(cur_instance.clone());
11551156

1156-
let prim_list = PrimitiveList::new(
1157-
prims,
1158-
&self.resources.prim_interner,
1159-
);
1160-
11611157
// This is the acttual picture representing our 3D hierarchy root.
1162-
let container_picture = PicturePrimitive::new_image(
1163-
None,
1164-
Picture3DContext::In {
1165-
root_data: Some(Vec::new()),
1166-
ancestor_index,
1167-
},
1168-
stacking_context.pipeline_id,
1169-
stacking_context.frame_output_pipeline_id,
1170-
true,
1171-
stacking_context.requested_raster_space,
1172-
prim_list,
1173-
stacking_context.spatial_node_index,
1174-
max_clip,
1175-
&self.clip_store,
1158+
current_pic_index = PictureIndex(self.prim_store.pictures
1159+
.alloc()
1160+
.init(PicturePrimitive::new_image(
1161+
None,
1162+
Picture3DContext::In {
1163+
root_data: Some(Vec::new()),
1164+
ancestor_index,
1165+
},
1166+
stacking_context.pipeline_id,
1167+
stacking_context.frame_output_pipeline_id,
1168+
true,
1169+
stacking_context.requested_raster_space,
1170+
PrimitiveList::new(
1171+
prims,
1172+
&self.resources.prim_interner,
1173+
),
1174+
stacking_context.spatial_node_index,
1175+
max_clip,
1176+
&self.clip_store,
1177+
))
11761178
);
11771179

1178-
current_pic_index = self.prim_store.create_picture(container_picture);
1179-
11801180
cur_instance.kind = PrimitiveInstanceKind::Picture { pic_index: current_pic_index };
11811181
}
11821182

11831183
// For each filter, create a new image with that composite mode.
11841184
for filter in &stacking_context.composite_ops.filters {
11851185
let filter = filter.sanitize();
1186-
let prim_list = PrimitiveList::new(
1187-
vec![cur_instance.clone()],
1188-
&self.resources.prim_interner,
1189-
);
11901186

1191-
let filter_picture = PicturePrimitive::new_image(
1192-
Some(PictureCompositeMode::Filter(filter)),
1193-
Picture3DContext::Out,
1194-
stacking_context.pipeline_id,
1195-
None,
1196-
true,
1197-
stacking_context.requested_raster_space,
1198-
prim_list,
1199-
stacking_context.spatial_node_index,
1200-
max_clip,
1201-
&self.clip_store,
1187+
let filter_pic_index = PictureIndex(self.prim_store.pictures
1188+
.alloc()
1189+
.init(PicturePrimitive::new_image(
1190+
Some(PictureCompositeMode::Filter(filter)),
1191+
Picture3DContext::Out,
1192+
stacking_context.pipeline_id,
1193+
None,
1194+
true,
1195+
stacking_context.requested_raster_space,
1196+
PrimitiveList::new(
1197+
vec![cur_instance.clone()],
1198+
&self.resources.prim_interner,
1199+
),
1200+
stacking_context.spatial_node_index,
1201+
max_clip,
1202+
&self.clip_store,
1203+
))
12021204
);
1203-
let filter_pic_index = self.prim_store.create_picture(filter_picture);
1204-
current_pic_index = filter_pic_index;
12051205

1206+
current_pic_index = filter_pic_index;
12061207
cur_instance.kind = PrimitiveInstanceKind::Picture { pic_index: current_pic_index };
12071208

12081209
if cur_instance.is_chased() {
@@ -1216,26 +1217,26 @@ impl<'a> DisplayListFlattener<'a> {
12161217

12171218
// Same for mix-blend-mode.
12181219
if let Some(mix_blend_mode) = stacking_context.composite_ops.mix_blend_mode {
1219-
let prim_list = PrimitiveList::new(
1220-
vec![cur_instance.clone()],
1221-
&self.resources.prim_interner,
1220+
let blend_pic_index = PictureIndex(self.prim_store.pictures
1221+
.alloc()
1222+
.init(PicturePrimitive::new_image(
1223+
Some(PictureCompositeMode::MixBlend(mix_blend_mode)),
1224+
Picture3DContext::Out,
1225+
stacking_context.pipeline_id,
1226+
None,
1227+
true,
1228+
stacking_context.requested_raster_space,
1229+
PrimitiveList::new(
1230+
vec![cur_instance.clone()],
1231+
&self.resources.prim_interner,
1232+
),
1233+
stacking_context.spatial_node_index,
1234+
max_clip,
1235+
&self.clip_store,
1236+
))
12221237
);
12231238

1224-
let blend_picture = PicturePrimitive::new_image(
1225-
Some(PictureCompositeMode::MixBlend(mix_blend_mode)),
1226-
Picture3DContext::Out,
1227-
stacking_context.pipeline_id,
1228-
None,
1229-
true,
1230-
stacking_context.requested_raster_space,
1231-
prim_list,
1232-
stacking_context.spatial_node_index,
1233-
max_clip,
1234-
&self.clip_store,
1235-
);
1236-
let blend_pic_index = self.prim_store.create_picture(blend_picture);
12371239
current_pic_index = blend_pic_index;
1238-
12391240
cur_instance.kind = PrimitiveInstanceKind::Picture { pic_index: blend_pic_index };
12401241

12411242
if cur_instance.is_chased() {
@@ -1553,31 +1554,31 @@ impl<'a> DisplayListFlattener<'a> {
15531554
// No point in adding a shadow here if there were no primitives
15541555
// added to the shadow.
15551556
if !prims.is_empty() {
1556-
let prim_list = PrimitiveList::new(
1557-
prims,
1558-
&self.resources.prim_interner,
1559-
);
1560-
15611557
// Create a picture that the shadow primitives will be added to. If the
15621558
// blur radius is 0, the code in Picture::prepare_for_render will
15631559
// detect this and mark the picture to be drawn directly into the
15641560
// parent picture, which avoids an intermediate surface and blur.
15651561
let blur_filter = FilterOp::Blur(std_deviation).sanitize();
1566-
let mut shadow_pic = PicturePrimitive::new_image(
1567-
Some(PictureCompositeMode::Filter(blur_filter)),
1568-
Picture3DContext::Out,
1569-
pipeline_id,
1570-
None,
1571-
is_passthrough,
1572-
raster_space,
1573-
prim_list,
1574-
pending_shadow.clip_and_scroll.spatial_node_index,
1575-
max_clip,
1576-
&self.clip_store,
1577-
);
15781562

15791563
// Create the primitive to draw the shadow picture into the scene.
1580-
let shadow_pic_index = self.prim_store.create_picture(shadow_pic);
1564+
let shadow_pic_index = PictureIndex(self.prim_store.pictures
1565+
.alloc()
1566+
.init(PicturePrimitive::new_image(
1567+
Some(PictureCompositeMode::Filter(blur_filter)),
1568+
Picture3DContext::Out,
1569+
pipeline_id,
1570+
None,
1571+
is_passthrough,
1572+
raster_space,
1573+
PrimitiveList::new(
1574+
prims,
1575+
&self.resources.prim_interner,
1576+
),
1577+
pending_shadow.clip_and_scroll.spatial_node_index,
1578+
max_clip,
1579+
&self.clip_store,
1580+
))
1581+
);
15811582

15821583
let shadow_prim_key = PrimitiveKey::new(
15831584
true,
@@ -2203,26 +2204,25 @@ impl FlattenedStackingContext {
22032204
Picture3DContext::Out => panic!("Unexpected out of 3D context"),
22042205
};
22052206

2206-
let prim_list = PrimitiveList::new(
2207-
mem::replace(&mut self.primitives, Vec::new()),
2208-
prim_interner,
2209-
);
2210-
2211-
let container_picture = PicturePrimitive::new_image(
2212-
Some(PictureCompositeMode::Blit),
2213-
flat_items_context_3d,
2214-
self.pipeline_id,
2215-
None,
2216-
true,
2217-
self.requested_raster_space,
2218-
prim_list,
2219-
self.spatial_node_index,
2220-
LayoutRect::max_rect(),
2221-
clip_store,
2207+
let pic_index = PictureIndex(prim_store.pictures
2208+
.alloc()
2209+
.init(PicturePrimitive::new_image(
2210+
Some(PictureCompositeMode::Blit),
2211+
flat_items_context_3d,
2212+
self.pipeline_id,
2213+
None,
2214+
true,
2215+
self.requested_raster_space,
2216+
PrimitiveList::new(
2217+
mem::replace(&mut self.primitives, Vec::new()),
2218+
prim_interner,
2219+
),
2220+
self.spatial_node_index,
2221+
LayoutRect::max_rect(),
2222+
clip_store,
2223+
))
22222224
);
22232225

2224-
let pic_index = prim_store.create_picture(container_picture);
2225-
22262226
Some(PrimitiveInstance::new(
22272227
PrimitiveInstanceKind::Picture { pic_index },
22282228
self.primitive_data_handle,

webrender/src/frame_builder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ impl FrameBuilder {
338338
let mut profile_counters = FrameProfileCounters::new();
339339
profile_counters
340340
.total_primitives
341-
.set(self.prim_store.prim_count);
341+
.set(self.prim_store.prim_count());
342342

343343
resource_cache.begin_frame(stamp);
344344
gpu_cache.begin_frame(stamp.frame_id());

webrender/src/prim_store.rs

+6-13
Original file line numberDiff line numberDiff line change
@@ -2576,10 +2576,6 @@ pub struct PrimitiveStore {
25762576

25772577
/// List of animated opacity bindings for a primitive.
25782578
pub opacity_bindings: OpacityBindingStorage,
2579-
2580-
/// Total count of primitive instances contained in pictures.
2581-
/// This is used for profile counters only.
2582-
pub prim_count: usize,
25832579
}
25842580

25852581
impl PrimitiveStore {
@@ -2589,7 +2585,6 @@ impl PrimitiveStore {
25892585
text_runs: TextRunStorage::new(stats.text_run_count),
25902586
images: ImageInstanceStorage::new(stats.image_count),
25912587
opacity_bindings: OpacityBindingStorage::new(stats.opacity_binding_count),
2592-
prim_count: 0,
25932588
}
25942589
}
25952590

@@ -2602,14 +2597,12 @@ impl PrimitiveStore {
26022597
}
26032598
}
26042599

2605-
pub fn create_picture(
2606-
&mut self,
2607-
prim: PicturePrimitive,
2608-
) -> PictureIndex {
2609-
let index = PictureIndex(self.pictures.len());
2610-
self.prim_count += prim.prim_list.prim_instances.len();
2611-
self.pictures.push(prim);
2612-
index
2600+
/// Returns the total count of primitive instances contained in pictures.
2601+
pub fn prim_count(&self) -> usize {
2602+
self.pictures
2603+
.iter()
2604+
.map(|p| p.prim_list.prim_instances.len())
2605+
.sum()
26132606
}
26142607

26152608
/// Update a picture, determining surface configuration,

webrender/src/util.rs

+39-1
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,50 @@ use euclid::{Point2D, Rect, Size2D, TypedPoint2D, TypedRect, TypedSize2D, Vector
88
use euclid::{TypedTransform2D, TypedTransform3D, TypedVector2D, TypedScale};
99
use num_traits::Zero;
1010
use plane_split::{Clipper, Polygon};
11-
use std::{i32, f32, fmt};
11+
use std::{i32, f32, fmt, ptr};
1212
use std::borrow::Cow;
1313

14+
1415
// Matches the definition of SK_ScalarNearlyZero in Skia.
1516
const NEARLY_ZERO: f32 = 1.0 / 4096.0;
1617

18+
/// A typesafe helper that separates new value construction from
19+
/// vector growing, which allows LLVM to elide the value copy.
20+
#[must_use]
21+
pub struct Allocation<'a, T: 'a> {
22+
vec: &'a mut Vec<T>,
23+
index: usize,
24+
}
25+
26+
impl<'a, T> Allocation<'a, T> {
27+
#[inline(always)]
28+
pub fn init(self, value: T) -> usize {
29+
unsafe {
30+
ptr::write(self.vec.as_mut_ptr().add(self.index), value);
31+
self.vec.set_len(self.index + 1);
32+
}
33+
self.index
34+
}
35+
}
36+
37+
pub trait VecHelper<T> {
38+
fn alloc(&mut self) -> Allocation<T>;
39+
}
40+
41+
impl<T> VecHelper<T> for Vec<T> {
42+
fn alloc(&mut self) -> Allocation<T> {
43+
let index = self.len();
44+
if self.capacity() == index {
45+
self.reserve(1);
46+
}
47+
Allocation {
48+
vec: self,
49+
index,
50+
}
51+
}
52+
}
53+
54+
1755
// Represents an optimized transform where there is only
1856
// a scale and translation (which are guaranteed to maintain
1957
// an axis align rectangle under transformation). The

0 commit comments

Comments
 (0)