Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upNew bincode-based IPC model #1181
Conversation
|
CC @TyOverby -- pretty good results! |
Remove Frame::pipeline_auxiliary_lists That should make perf comparisons on #1181 less skewed. cc @gankro <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/1182) <!-- Reviewable:end -->
|
#1182 results No noticeable difference. |
|
|
|
rebased -- nothing interesting changed if you had already started reviewing. |
|
|
|
It's probably just imports... alphabetical imports are a friggin nightmare |
|
Reviewed 14 of 19 files at r1, 4 of 4 files at r2. webrender/examples/basic.rs, line 196 at r2 (raw file):
nit: extra space webrender/src/render_backend.rs, line 208 at r2 (raw file):
nit: extra spaces here webrender_traits/Cargo.toml, line 15 at r2 (raw file):
Should this be alpha-7? webrender_traits/src/channel.rs, line 53 at r2 (raw file):
Can this be re-enabled? wrench/src/yaml_frame_writer.rs, line 481 at r2 (raw file):
Perhaps use a Comments from Reviewable |
|
Partial review of the simple diffs - more coming. |
|
Reviewed 5 of 19 files at r1. webrender/src/frame_builder.rs, line 405 at r2 (raw file):
Similar to other comments - I'm unsure why a count in addition to range is needed here? webrender/src/prim_store.rs, line 251 at r2 (raw file):
Why the count here? Isn't it part of the item range? webrender_traits/src/display_item.rs, line 424 at r2 (raw file):
Why do we need a complex_clip_count here (isn't it available in the ItemRange above)? webrender_traits/src/display_list.rs, line 44 at r2 (raw file):
nit: spelling webrender_traits/src/display_list.rs, line 80 at r2 (raw file):
nit: separate lines webrender_traits/src/display_list.rs, line 156 at r2 (raw file):
|
|
@gankro Hmm, the reviewable comments above don't seem to render correctly for me - hopefully they show up OK in reviewable itself. In general this looks great! My main questions are related to the item counts that seem to be passed around along with item ranges, and also what the complexities are with how gradient stops are handled compared to glyphs. There's also a couple of TODO comments that seem like they might need to be resolved before merging. It'd also be good for @kvark and / or @mrobinson to take a look over this too if they have time :) |
|
Looks good! We discussed the need to pass
Review status: all files reviewed at latest revision, 25 unresolved discussions, some commit checks failed. webrender/doc/CLIPPING.md, line 15 at r2 (raw file):
looks sweet! webrender_traits/src/display_list.rs, line 214 at r2 (raw file):
that's spooky Comments from Reviewable |
|
Phwew. This is a big patch. I like that you've been able to eliminate auxiliary_data. I did a once-over review, identify mainly style issues. |
| @@ -191,6 +191,29 @@ impl webrender_traits::RenderNotifier for Notifier { | |||
| } | |||
| } | |||
|
|
|||
| fn push_sub_clip(api: &RenderApi, builder: &mut DisplayListBuilder, bounds: &LayoutRect) | |||
| -> ClipRegionToken { | |||
This comment has been minimized.
This comment has been minimized.
mrobinson
May 2, 2017
Member
The indentation style for Servo and WebRender is:
fn push_sub_clip(api: &RenderApi,
builder: &mut DisplayListBuilder,
bounds: &LayoutRect)
-> ClipRegionToken {
| mask_image, | ||
| ImageDescriptor::new(2, 2, ImageFormat::A8, true), | ||
| ImageData::new(vec![0, 80, 180, 255]), | ||
| None, |
This comment has been minimized.
This comment has been minimized.
mrobinson
May 2, 2017
Member
Indentation here should look like:
api.add_image(mask_image,
ImageDescriptor::new(2, 2, ImageFormat::A8, true),
ImageData::new(vec![0, 80, 180, 255]),
None);
I realize this had the funky indentation before, but this is a good moment to fix it.
|
|
||
| pub fn get<T>(&self, range: ItemRange<T>) -> AuxIter<T> | ||
| where T: Deserialize, | ||
| { |
This comment has been minimized.
This comment has been minimized.
| pub struct ItemRange<T> { | ||
| start: usize, | ||
| length: usize, | ||
| _boo: PhantomData<T>, |
This comment has been minimized.
This comment has been minimized.
|
|
||
| impl<'a, T> AuxIter<'a, T> | ||
| where T: Deserialize, | ||
| { |
This comment has been minimized.
This comment has been minimized.
mrobinson
May 2, 2017
Member
This can all be one line. { in WebRender never gets its own line. I guess this can be considered a general comment for the whole PR.
| let mut continue_traversal: Option<BuiltDisplayListIter<'a>> = None; | ||
| loop { | ||
| if let Some(trav) = continue_traversal.take() { *traversal = trav; } | ||
| let item = if let Some(item) = traversal.next() { item } else { break }; |
This comment has been minimized.
This comment has been minimized.
mrobinson
May 2, 2017
Member
This might be better expressed as a match:
let item = match traversal.next() {
Some(item) => item,
None => break,
};
| use webrender_traits::{GlyphOptions, ImageKey, ImageRendering, ItemRange, LayerPoint, LayerRect}; | ||
| use webrender_traits::{LayerSize, LayerToScrollTransform, PipelineId, RepeatMode, TileOffset}; | ||
| use webrender_traits::{TransformStyle, WebGLContextId, YuvColorSpace, YuvData}; | ||
| use webrender_traits::{GlyphInstance, GlyphOptions, GradientStop, ImageKey, ImageRendering, ItemRange, LayerPoint, LayerRect, LayerSize}; |
This comment has been minimized.
This comment has been minimized.
| info.gradient.stops, | ||
| item.gradient_stops(), | ||
| item.display_list() | ||
| .get(item.gradient_stops()).count(), |
This comment has been minimized.
This comment has been minimized.
mrobinson
May 2, 2017
Member
I think it makes sense to add a method to item that returns a tuple containing the gradients_stops and the count together.
| @@ -318,11 +319,7 @@ impl Clone for GradientData { | |||
|
|
|||
| impl GradientData { | |||
| // Generate a color ramp between the start and end indexes from a start color to an end color. | |||
| fn fill_colors(&mut self, start_idx: usize, end_idx: usize, start_color: &ColorF, end_color: &ColorF) -> usize { | |||
| if start_idx >= end_idx { | |||
This comment has been minimized.
This comment has been minimized.
mrobinson
May 2, 2017
Member
If this cannot happen any longer, let's add an assertion here that shows it.
| // Preconditions (should be ensured by DisplayListBuilder): | ||
| // * we have at least two stops | ||
| // * first stop has offset 0.0 | ||
| // * last stop has offset 1.0 |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Gankra
May 2, 2017
Author
Contributor
I did; the new debug_asserts and unwrap that imply these assumptions. I just wrote the actual assumption out to explain those asserts/unwrap.
This comment has been minimized.
This comment has been minimized.
|
@glennw some high level details about your questions: Why are some aux lists prefix and some postfix?This can potentially be eliminated (making them all postfix), but this was done to minimally disrupt Servo and Gecko's implementations. Minimal disruption was a goal of mine to minimize the number of places I could make a mistake, since this is a fairly large change that touches a lot of different things. Essentially, gradient stops and complex clips are pushed into the aux list before the element that uses them, via create_* APIs. So I need to be able to push that data into the display list before the actual item that uses them. This should be relatively easy for complex clips, but is harder to fix for GradientStops -- gradients are embedded in a nested type, and their presence can't be determined just by the SpecificDisplayItem. Glyphs and filters, on the other hand, are provided at the time of pushing in the SpecificDisplayItem, and so can be stored in implicit postfix position. This difference is also why I'm passing around So I added a zero-sized-move-only token type that Why is count and ItemRange provided?An ItemRange is now the byte range in which a serialized slice of the given type can be found. The format of this slice is So at a basic level, the
Finally the fact that The Remaining TODOs
|
|
@gankro thanks for the
This actually worries me. I'd prefer us leaving the |
|
@gankro Thanks for the explanation - that makes sense, and I definitely agree with minimal disruption to callers! Should we open an issue to consider making all those items postfix as a follow up? Would that make things more consistent in the long term? |
|
@kvark I felt push_* emphasized the transientness -- maybe set_* would be even better? @glennw yes an issue sounds like a good idea. From my work on integrating these changes into gecko and servo, it seems like clip_region should be very easy to do, but I'm still not sure about how to do gradients well. The deserializer can do a deep match to find everything that would have gradients, but how to restructure the builder API is unclear to me. I wouldn't feel too bad if gradients were cursed to forever be prefix, since afaict they're super rare. |
9b16e57
to
19fd384
|
Rebased, pushed up fixes to almost everything. Because git is complicated, some stuff ended up getting squashed into earlier commits. e.g. my changes to the examples and the impl for push_built_display_list are squashed into the relevant commits. The "fixup impl" stuff I'll squash after review, and has most of the changes. |
|
TODO:
|
|
Ok yeah that assertion is still broken. I have no idea where those trailing zeros are coming from, and it scares me, but everything seems to be working so I'm inclined to file an issue and call it a day. |
|
I've run this against Servo master with the CSS and WPT tests successfully. Also did a bit of informal testing, and all seemed to be working OK. The trailing bytes is a bit scary, but I'm OK with merging this now since it's going to bit-rot quickly otherwise. @gankro Is this ready to merge from your perspective? |
|
Assuming y'all are fine with calling it push_clip_region |
I see it as a part of a bigger (naming) problem, affecting more stuff than just clip regions. We can (and should!) address this in follow-ups. Also, I believe that @mrobinson notes have been addressed as well. Going to merge in 20 minutes, unless there are any objections. |
|
I think my concerns have been answered, so I'm okay with merging this. Before merging though, I have a few more style nits. |
| self.cur_clip = ClipRegion::empty(); | ||
|
|
||
| loop { | ||
| if self.data.len() == 0 { return None } |
This comment has been minimized.
This comment has been minimized.
mrobinson
May 3, 2017
Member
We should probably use newlines here, the single line style is not something that we typically use in WebRender as far as I know.
| let mut continue_traversal = None; | ||
| loop { | ||
| if let Some(traversal) = continue_traversal.take() { *list_iterator = traversal; } | ||
| let base = if let Some(base) = list_iterator.next() { base } else { break }; |
This comment has been minimized.
This comment has been minimized.
| // continue_traversal is a big borrowck hack | ||
| let mut continue_traversal = None; | ||
| loop { | ||
| if let Some(traversal) = continue_traversal.take() { *list_iterator = traversal; } |
This comment has been minimized.
This comment has been minimized.
|
@rlhunt's nits addressed in newest commit (will squash when ready) |
This replaces the existing unsound IPC with new sound and validated bincode-based IPC. On my laptop this regresses mean display list IPC time from 1.5ms to 1.8ms, which is reasonable enough to land and optimize later. Major differences: * We never construct a `Vec<DisplayItem>` any more. DisplayListBuilder directly serializes the data into a Vec<u8>. The backend similarly deserializes data on-the-fly. This reduces the memory footprint of BuiltDisplayLists, and eliminates several copies/allocations. * AuxiliaryLists are no more. Auxiliary data is stored in the DisplayList next to the relevant item. When streaming the data out, we skip over these lists and just produce ItemRanges, similar to the old API. To do this while minimally impacting the rest of webrender and its consumers, there are two new "dummy" DisplayItems: SetGradientStops and SetClipRegion. These affect the subsequent DisplayItem, and will never be yielded by the BuiltDisplayListIter. * DisplayItem no longer stores any ItemRanges or a ClipRegion. Instead these values are stored "on the side" and can be requested from the item yielded by BuiltDisplayListIter. This necessitates threading some additional state for certain methods. Notably number-of-items and size-of-item-range are no longer equivalent, and the former must therefore be threaded separately. ItemRange's fields have been made private to prevent anyone from relying on this. * ItemRanges are now typed. This makes type declarations clearer, prevents theoretical bugs, and gives DisplayList a nicer API for getting auxiliary data. * I needed to rewrite some of the gradient code, as it was relying on reverse iteration of auxiliary data, which is no longer supported. @rlhunt has approved my new implementation. NOTE: this changes some public APIs and will need some changes in Servo and Gecko. I'll work on those follow ups next week.
|
Sorry I meant @mrobinson's comments. Also squashed. |
|
Thanks @gankro ! Sounds like we are ready to take off. |
|
|
New bincode-based IPC model This replaces the existing unsound IPC with new sound and validated bincode-based IPC. On my laptop this regresses mean display list IPC time from 1.5ms to 1.8ms, which is reasonable enough to land and optimize later. Major differences: * We never construct a `Vec<DisplayItem>` any more. DisplayListBuilder directly serializes the data into a Vec<u8>. The backend similarly deserializes data on-the-fly. This reduces the memory footprint of BuiltDisplayLists, and eliminates several copies/allocations. * AuxiliaryLists are no more. Auxiliary data is stored in the DisplayList next to the relevant item. When streaming the data out, we skip over these lists and just produce ItemRanges, similar to the old API. To do this while minimally impacting the rest of webrender and its consumers, there are two new "dummy" DisplayItems: SetGradientStops and SetClipRegion. These affect the subsequent DisplayItem, and will never be yielded by the BuiltDisplayListIter. * DisplayItem no longer stores any ItemRanges or a ClipRegion. Instead these values are stored "on the side" and can be requested from the item yielded by BuiltDisplayListIter. This necessitates threading some additional state for certain methods. Notably number-of-items and size-of-item-range are no longer equivalent, and the former must therefore be threaded separately. ItemRange's fields have been made private to prevent anyone from relying on this. * ItemRanges are now typed. This makes type declarations clearer, prevents theoretical bugs, and gives DisplayList a nicer API for getting auxiliary data. * I needed to rewrite some of the gradient code, as it was relying on reverse iteration of auxiliary data, which is no longer supported. @rlhunt has approved my new implementation. NOTE: this changes some public APIs and will need some changes in Servo and Gecko. I'll work on those follow ups next week. With Transmute (Before This PR): <img width="539" alt="ipc-with-transmute" src="https://cloud.githubusercontent.com/assets/1136864/25545859/924c1848-2c2e-11e7-9833-efb2c8612ca0.png"> With Bincode (After This PR): <img width="535" alt="ipc-with-bincode" src="https://cloud.githubusercontent.com/assets/1136864/25545858/924bc9a6-2c2e-11e7-9288-80a6ad8e671b.png"> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/1181) <!-- Reviewable:end -->
|
|
Update to webrender's new bincode IPC **DO NO MERGE YET** This is the required update to Servo for my changes to webrender in servo/webrender#1181 <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16652) <!-- Reviewable:end -->
…kro:bincode-ipc-5); r=jdm **DO NO MERGE YET** This is the required update to Servo for my changes to webrender in servo/webrender#1181 Source-Repo: https://github.com/servo/servo Source-Revision: 74c36cb35ddac3bf7db9215d85b9d4d7a660197b
…kro:bincode-ipc-5); r=jdm **DO NO MERGE YET** This is the required update to Servo for my changes to webrender in servo/webrender#1181 Source-Repo: https://github.com/servo/servo Source-Revision: 74c36cb35ddac3bf7db9215d85b9d4d7a660197b --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 3f1a55f6dab59aa865e929b9fb36fb1572708bc1
…kro:bincode-ipc-5); r=jdm **DO NO MERGE YET** This is the required update to Servo for my changes to webrender in servo/webrender#1181 Source-Repo: https://github.com/servo/servo Source-Revision: 74c36cb35ddac3bf7db9215d85b9d4d7a660197b
…kro:bincode-ipc-5); r=jdm **DO NO MERGE YET** This is the required update to Servo for my changes to webrender in servo/webrender#1181 Source-Repo: https://github.com/servo/servo Source-Revision: 74c36cb35ddac3bf7db9215d85b9d4d7a660197b UltraBlame original commit: 47b6c862df37044dde83d5e18f74872e4ed1d7a1
…kro:bincode-ipc-5); r=jdm **DO NO MERGE YET** This is the required update to Servo for my changes to webrender in servo/webrender#1181 Source-Repo: https://github.com/servo/servo Source-Revision: 74c36cb35ddac3bf7db9215d85b9d4d7a660197b UltraBlame original commit: 47b6c862df37044dde83d5e18f74872e4ed1d7a1
…kro:bincode-ipc-5); r=jdm **DO NO MERGE YET** This is the required update to Servo for my changes to webrender in servo/webrender#1181 Source-Repo: https://github.com/servo/servo Source-Revision: 74c36cb35ddac3bf7db9215d85b9d4d7a660197b UltraBlame original commit: 47b6c862df37044dde83d5e18f74872e4ed1d7a1

Gankra commentedApr 28, 2017
•
edited by larsbergstrom
This replaces the existing unsound IPC with new sound and validated bincode-based IPC. On my laptop this regresses mean display list IPC time from 1.5ms to 1.8ms, which is reasonable enough to land and optimize later.
Major differences:
We never construct a
Vec<DisplayItem>any more. DisplayListBuilder directly serializes the data into a Vec. The backend similarly deserializes data on-the-fly. This reduces the memory footprint of BuiltDisplayLists, and eliminates several copies/allocations.AuxiliaryLists are no more. Auxiliary data is stored in the DisplayList next to the relevant item. When streaming the data out, we skip over these lists and just produce ItemRanges, similar to the old API. To do this while minimally impacting the rest of webrender and its consumers, there are two new "dummy" DisplayItems: SetGradientStops and SetClipRegion. These affect the subsequent DisplayItem, and will never be yielded by the BuiltDisplayListIter.
DisplayItem no longer stores any ItemRanges or a ClipRegion. Instead these values are stored "on the side" and can be requested from the item yielded by BuiltDisplayListIter. This necessitates threading some additional state for certain methods. Notably number-of-items and size-of-item-range are no longer equivalent, and the former must therefore be threaded separately. ItemRange's fields have been made private to prevent anyone from relying on this.
ItemRanges are now typed. This makes type declarations clearer, prevents theoretical bugs, and gives DisplayList a nicer API for getting auxiliary data.
I needed to rewrite some of the gradient code, as it was relying on reverse iteration of auxiliary data, which is no longer supported. @rlhunt has approved my new implementation.
NOTE: this changes some public APIs and will need some changes in Servo and Gecko. I'll work on those follow ups next week.
wr-stats in Servo:
With Transmute (Before This PR):

With Bincode (After This PR):

This change is