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

Use FastTransform almost everywhere #2444

Merged

Conversation

@mrobinson
Copy link
Member

mrobinson commented Feb 20, 2018

This helps to avoid the cost of expensive matrix math and allows us to
more liberally call things like inverse() on our transformations,
since the worst case is that we will be retrieving the already-cached
inverted matrix. This decreases the amount of time that
FrameBuilder::build takes in my local CPU profiles.


This change is Reviewable

@mrobinson mrobinson requested review from kvark and glennw Feb 20, 2018
@mrobinson
Copy link
Member Author

mrobinson commented Feb 20, 2018

Gecko try job for this change is here: https://treeherder.mozilla.org/#/jobs?repo=try&revision=2f8bc89e36afa986e5f3ea8011caeec007b66cc9

The build failures seem to be unrelated infrastructure issues.

@kvark
Copy link
Member

kvark commented Feb 20, 2018

Reviewed 8 of 8 files at r1.
Review status: all files reviewed at latest revision, 15 unresolved discussions, some commit checks failed.


webrender/src/clip_scroll_node.rs, line 183 at r1 (raw file):

        let source_perspective = source_perspective.map_or_else(
            LayoutTransformOrOffset::identity,
            |perspective| LayoutTransformOrOffset::new_transform(perspective)

nit: could just be LayoutTransformOrOffset::new_transform


webrender/src/prim_store.rs, line 1475 at r1 (raw file):

                    local_clip_rect
                } else {
                    let clip_transform = LayerToWorldTransformOrOffset::new_transform(

nit: it could also just implement From<Transform> and From<Vector> instead of constructors


webrender/src/util.rs, line 157 at r1 (raw file):

pub fn calculate_screen_bounding_rect(
    transform: &TransformOrOffset<LayerPixel, WorldPixel>,

nit: use the new alias here


webrender/src/util.rs, line 347 at r1 (raw file):

/// when possible when dealing with non-perspective axis-aligned transformations.
#[derive(Debug, Clone, Copy)]
pub enum TransformOrOffset<Src, D> {

we should be consistent in naming of those generic arguments


webrender/src/util.rs, line 347 at r1 (raw file):

/// when possible when dealing with non-perspective axis-aligned transformations.
#[derive(Debug, Clone, Copy)]
pub enum TransformOrOffset<Src, D> {

I don't think name like XOrY is elegant. It exposes the internal detail. What is important here is that this is a transform, it quacks like one, maybe not exactly a Matrix4, but can be converted into it. So maybe FastTransform? More opinions are welcome :)


webrender/src/util.rs, line 349 at r1 (raw file):

pub enum TransformOrOffset<Src, D> {
    /// A simple offset, which can be used without doing any matrix math.
    Offset(TypedVector2D<f32, Src>),

I think this should use the destination space - makes it more convenient for the using code


webrender/src/util.rs, line 358 at r1 (raw file):

    },

    //Uninvertible,

is this comment needed?


webrender/src/util.rs, line 371 at r1 (raw file):

    #[inline(always)]
    pub fn new_transform(transform: TypedTransform3D<f32, Src, D>) -> Self {

doesn't look to be consistent with with_offset constructor


webrender/src/util.rs, line 380 at r1 (raw file):

    }

    pub fn to_transform(&self) -> TypedTransform3D<f32, Src, D> {

could probably just implement Into<>


webrender/src/util.rs, line 391 at r1 (raw file):

        match *self {
            TransformOrOffset::Offset(..) => true,
            TransformOrOffset::Transform { inverse, .. } => inverse.is_some(),

ref inverse should avoid copies


webrender/src/util.rs, line 402 at r1 (raw file):

        match (self, other) {
            (&TransformOrOffset::Offset(ref offset), &TransformOrOffset::Offset(ref other_offset)) => {
                let offset = TypedVector2D::from_untyped(&offset.to_untyped());

nit: could also do offset * TypedScale::<_, NewSrc, D>::new(1.0)


webrender/src/util.rs, line 407 at r1 (raw file):

            _ => {
                let new_transform = self.to_transform().pre_mul(&other.to_transform());
                TransformOrOffset::new_transform(new_transform)

is it desirable to re-compute the inverse during each step of transformations like this one?


webrender/src/util.rs, line 417 at r1 (raw file):

            &TransformOrOffset::Offset(ref offset) =>
                return TransformOrOffset::Offset(*offset + *other_offset),
            &TransformOrOffset::Transform { transform, .. } =>

similarly, we probably want ref transform here and below


webrender/src/util.rs, line 442 at r1 (raw file):

    pub fn is_backface_visible(&self) -> bool {
        match *self {
            TransformOrOffset::Offset(..) => true,

I think this should be false


webrender/src/util.rs, line 483 at r1 (raw file):

                Some(inverse.transform_rect(&rect)),
            TransformOrOffset::Transform { transform, is_2d: false, .. } =>
                Some(transform.inverse_rect_footprint(rect)),

not required for this PR, but I think inverse_rect_footprint should return an Option itself


Comments from Reviewable

@mrobinson
Copy link
Member Author

mrobinson commented Feb 20, 2018

Review status: all files reviewed at latest revision, 15 unresolved discussions, some commit checks failed.


webrender/src/clip_scroll_node.rs, line 183 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

nit: could just be LayoutTransformOrOffset::new_transform

I think LayoutTransformOrOffset::identity is a little more efficient here.


webrender/src/prim_store.rs, line 1475 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

nit: it could also just implement From<Transform> and From<Vector> instead of constructors

Good idea!


webrender/src/util.rs, line 157 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

nit: use the new alias here

Nice catch.


webrender/src/util.rs, line 347 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

we should be consistent in naming of those generic arguments

Also here. I had planned to fix this, but it got lost during the day.


webrender/src/util.rs, line 347 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

I don't think name like XOrY is elegant. It exposes the internal detail. What is important here is that this is a transform, it quacks like one, maybe not exactly a Matrix4, but can be converted into it. So maybe FastTransform? More opinions are welcome :)

I'm happy to rename this to FastTransform.


webrender/src/util.rs, line 349 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

I think this should use the destination space - makes it more convenient for the using code

When it's an offset the Src and Dst are the same unit. I'm not sure how to express this in the type system. I tested changing this to Dst and it seems that it complicates a lot of callsites. Choosing one or the other will have convenience tradeoffs. Using Src keeps almost all of the to_untyped``/ from_untypedstuff inside the struct implementation, which I think is a good indication thatSrc` is the correct choice here.


webrender/src/util.rs, line 358 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

is this comment needed?

This was left over. I'll remove it.


webrender/src/util.rs, line 371 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

doesn't look to be consistent with with_offset constructor

Fixed.


webrender/src/util.rs, line 380 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

could probably just implement Into<>

Done.


webrender/src/util.rs, line 391 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

ref inverse should avoid copies

Done.


webrender/src/util.rs, line 402 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

nit: could also do offset * TypedScale::<_, NewSrc, D>::new(1.0)

It's hard to say which version is more readable, but I think it's a bit easier to read without the angle brackets.


webrender/src/util.rs, line 407 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

is it desirable to re-compute the inverse during each step of transformations like this one?

It's not necessary and we could specialize this even further, but I wanted to avoid premature optimization here.


webrender/src/util.rs, line 417 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

similarly, we probably want ref transform here and below

Done.


webrender/src/util.rs, line 442 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

I think this should be false

Thanks! Fixed.


webrender/src/util.rs, line 483 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

not required for this PR, but I think inverse_rect_footprint should return an Option itself

Okay. That's a good change for the future.


Comments from Reviewable

@mrobinson mrobinson force-pushed the mrobinson:transform-or-offset-almost-everywhere branch from e5d4864 to 8fe094e Feb 20, 2018
@mrobinson mrobinson changed the title Use TransformOrOffset almost everywhere Use FastTransform almost everywhere Feb 20, 2018
@mrobinson
Copy link
Member Author

mrobinson commented Feb 20, 2018

@kvark Thanks for the excellent review. I think I have answered almost all of your concerns, but let me know if I missed anything.

@kvark
Copy link
Member

kvark commented Feb 20, 2018

Thanks for addressing my concerns! We are almost there :)


Reviewed 8 of 8 files at r2.
Review status: all files reviewed at latest revision, 4 unresolved discussions.


webrender/src/clip_scroll_node.rs, line 183 at r1 (raw file):

Previously, mrobinson (Martin Robinson) wrote…

I think LayoutTransformOrOffset::identity is a little more efficient here.

this comment was about the line you changed to |perspective| perspective.into(), which btw could also be written as From::from


webrender/src/util.rs, line 371 at r1 (raw file):

Previously, mrobinson (Martin Robinson) wrote…

Fixed.

do we still need the constructors though?..


webrender/src/util.rs, line 402 at r1 (raw file):

Previously, mrobinson (Martin Robinson) wrote…

It's hard to say which version is more readable, but I think it's a bit easier to read without the angle brackets.

Sure, I don't hold strong feelings about this. Just seeing untyped makes me cringe :)


webrender/src/util.rs, line 115 at r2 (raw file):

        }

        self.m43 < NEARLY_ZERO

I think this should come with abs()


Comments from Reviewable

@mrobinson
Copy link
Member Author

mrobinson commented Feb 20, 2018

Review status: all files reviewed at latest revision, 4 unresolved discussions.


webrender/src/util.rs, line 371 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

do we still need the constructors though?..

The constructors are still used in a couple places to avoid having to use explicitly specify the types in order to satisfy the type inference. I think it's better to be explicit in those cases rather than rely on the inference + writing the type.


webrender/src/util.rs, line 115 at r2 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

I think this should come with abs()

Okay. Fixed.


Comments from Reviewable

FastTransform used to be called TransformOrOffset and this change uses it
in a lot of places that we used to use TypedTransform3D directly. This
helps to avoid the cost of expensive matrix math and allows us to more
liberally call things like `inverse()` on our transformations, since the
worst case is that we will be retrieving the already-cached inverted
matrix. This decreases the amount of time that FrameBuilder::build takes
in my local CPU profiles.
@mrobinson mrobinson force-pushed the mrobinson:transform-or-offset-almost-everywhere branch from 8fe094e to 8c3bf9c Feb 20, 2018
@kvark
Copy link
Member

kvark commented Feb 20, 2018

@bors-servo
Copy link
Contributor

bors-servo commented Feb 20, 2018

📌 Commit 8c3bf9c has been approved by kvark

@bors-servo
Copy link
Contributor

bors-servo commented Feb 20, 2018

Testing commit 8c3bf9c with merge b2acbc9...

bors-servo added a commit that referenced this pull request Feb 20, 2018
…, r=kvark

Use FastTransform almost everywhere

This helps to avoid the cost of expensive matrix math and allows us to
more liberally call things like `inverse()` on our transformations,
since the worst case is that we will be retrieving the already-cached
inverted matrix. This decreases the amount of time that
FrameBuilder::build takes in my local CPU profiles.

<!-- 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/2444)
<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

bors-servo commented Feb 20, 2018

☀️ Test successful - status-appveyor, status-taskcluster, status-travis
Approved by: kvark
Pushing b2acbc9 to master...

@bors-servo bors-servo merged commit 8c3bf9c into servo:master Feb 20, 2018
3 of 4 checks passed
3 of 4 checks passed
code-review/reviewable 1 file, 4 discussions left (kvark, mrobinson)
Details
Taskcluster (pull_request) TaskGroup: success
Details
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
homu Test successful
Details
@mrobinson mrobinson deleted the mrobinson:transform-or-offset-almost-everywhere branch Feb 21, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

3 participants
You can’t perform that action at this time.