Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
trsh

Layer repaint sources a LAG in animation

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

So this is a classical processing pipe-line for GPU rendered animations via CSS transform:

 

1) We start start to animate a block from HTML with, for example, TweenLite.to(x:100...

2) At that moment (very start), what happens internally in browser, is that this block is Repainted to a separate composite layer.

3) This layer (when ready) is pushed to VRAM for fast access and animating.

4) Layer decomposes and clears from VRAM when the browser thinks it must.

 

And as we know this works pretty well!

 

But, Where my problem arises is POINT 2,3. On lower hardware, when the initial repaint happens and layer is pushed to VRAM, there is some 100-200ms LAG. And when the animation it self is 1sec or less, this LAG just kills it:

 

a) first of all there is a kind of a shutter at that moment,

B) secondly.. I start to see the object animation already 30% complete (for ex. if the animation is x from 0 - 100 in sec, I start to see it happening on x=>30), when the layer is ready.

 

The potential solutions:

 

1) Use will-change or empty transform to fool the browser, to push layer before animating.

 

Well.... will-change is kind of experimental and it might be removed, and does not work on IE. empty transform does't work on chrome any more. And the list goes on. And anyway, at some point the browse might consider destroying the layer (to much idle, etc.). So very unstable.

 

2) It would make sense to me, to animate an object via transform only when the repaint is finished. Otherwise it will always look crappy. As there are some tips out there http://stackoverflow.com/questions/14578356/how-to-detect-when-an-image-has-finished-rendering-in-the-browser-i-e-painted (i like second answer), how to detect the repaint happend, maybe this can be patched to GSAP?

 

What do u think of all this?

Link to comment
Share on other sites

Sorry for the misspelled topic :D . Seems I cant correct it.

Link to comment
Share on other sites

Hello,

 

I am confused by your question without seeing an example. Do you have a codepen demo so we can see your code in context?

 

 

Also I have some questions so we better understand what your seeing.

 

What browser and browser version?

 

What OS and OS version?

 

What CSS properties do you have on your elements?

 

In the DOM inspector do you see that the element is using translate() or translate3d() or matrix() or matrix3d() ??

 

That type of thing is important so you know if the element is being pushed on its own layer and given a new stacking context. GSAP has force3D: "auto" by default for the CSSPlugin. But it also depends on what CSS properties you have on your element!

 

Are you animating an <img> element or a background-image that might be affected by the old new WebKit chrome 49 and Chrome 53 bug?

 

Depending on the browser jank it can be easily remedied, no need to check MozAfter Paint. GSAP deals with all that. I think your over thinking this since it just sounds like a browser bug. Since your also asking about that MozAfterPaint event I presume your seeing this issue in Firefox. MozAfterPaint is a Firefox only event. Sounds like your seeing jank when translating x or y. Then you need to add this to your tween with x and y:

 

rotation:0.01

 

That will help resolve a translate jitter bug in Firefox. But it can be a number of things causing that jank, and we won't know what is happening unless we have code we can test. As well as answers to the above questions so we can better understand what your seeing.

 

Thanks! :)

  • Like 1
Link to comment
Share on other sites

Ok. Here is the codepen -> 

See the Pen LRxozR?editors=0110 by anon (@anon) on CodePen

 

OS: windows, Chrome (latest stable).

 

Instructions:

 

1) Open codepen ex. abowe

2) Open DevTools

3) Seek for Render tab in dev tools

4) Check there Paint flashing and FPS metter

5) Reload the page

6) Check the fps GPU memory

7) Press start button in my example

8) Notice a green flash (new layers created)

9) Check the GPU memory now (its grown, as layers pushed to VRAM)

10) After animation ended check VRAM (same as at beginning, layer is cleared)

 

Mark. You wont see no Performance problems, lags, whatsoever on a good computer, because the Painting the layer and pushing it to VRAM will just take 10 ms or less. On more shity device, you will experience a LAG (due repaint and push to VRAM) and probably start to witness the animation on half way. Is this clear enough?

Link to comment
Share on other sites

I'm confused by what you're asking. Is this about images? That's what you linked to on Stackoverflow, and using requestAnimationFrame isn't going let you know when an image has been painted. Look at how the background turns red on the 2nd frame request. Most of the images are only partially visible by that time.

See the Pen 30ae868b0710c66172b41aaf635e7652 by osublake (@osublake) on CodePen

 

Your code could be optimized too. Does this perform bad?

See the Pen d661897339563599d1fc9e3a1baf7b46 by osublake (@osublake) on CodePen

 

Here's a good thread about browser repaints.

http://greensock.com/forums/topic/14213-convert-css3-animation-to-gsap-for-performance-gain/

  • Like 2
Link to comment
Share on other sites

I'm confused by what you're asking. Is this about images? That's what you linked to on Stackoverflow, and using requestAnimationFrame isn't going let you know when an image has been painted. Look at how the background turns red on the 2nd frame request. Most of the images are only partially visible by that time.

See the Pen 30ae868b0710c66172b41aaf635e7652 by osublake (@osublake) on CodePen

 

Your code could be optimized too. Does this perform bad?

See the Pen d661897339563599d1fc9e3a1baf7b46 by osublake (@osublake) on CodePen

 

Here's a good thread about browser repaints.

http://greensock.com/forums/topic/14213-convert-css3-animation-to-gsap-for-performance-gain/

 

1) It sucks that requestAnimationFrame method doesn't do the job :(

 

2) You present a very simplified case. This example performs bad 

See the Pen amJoQk by anon (@anon) on CodePen

. You can force3d on "inside" box, what will be slow because parent matrix is added to child on every frame. Or you Don't force - then the child box is repainted right in the middle of animation and causes my described lag. Neither performance solution is good. If the inside Box would wait until is painted, and then move, it would solve my problem.

Link to comment
Share on other sites

This kind of solves the above perf. problem ->

See the Pen ORpLKB by anon (@anon) on CodePen

, but I'm guessing the repaint time = ".4", and that's no good in the end :/

Link to comment
Share on other sites

That's what you linked to on Stackoverflow, and using requestAnimationFrame isn't going let you know when an image has been painted. Look at how the background turns red on the 2nd frame request. Most of the images are only partially visible by that time.

See the Pen 30ae868b0710c66172b41aaf635e7652 by osublake (@osublake) on CodePen

 

Btw this example confused me, and it's preload doesn't work at all. You can see in timeline that resources are downloaded twice. 

Link to comment
Share on other sites

I think it's the image service I'm using. This version will cache them.

See the Pen eb2ce19ff1c7b8c2e00074521c588761?editors=1111 by osublake (@osublake) on CodePen

 

And after doing that, the images look somewhat in sync with frame request, but I haven't tested it other browsers. You might want to double check how it works in IE/Edge and Safari.

  • Like 2
Link to comment
Share on other sites

I'm not seeing the issue you describe, i do see a slight hesitant on animation start. But that is because your animating an image, before it is fully loaded, and before the DOM is fully ready. As a rule of thumb especially if your going to be animating images you should always wait until the DOM is ready and the window is fully loaded.  And there is no need to keep turning on and off force3D, since "auto" does that for you.

 

Anytime you are testing performance in Google Chrome, you must use a new incognito mode tab or window. The Google Dev team recommends that you always test performance, paints, and frame timeline in a incognito mode tab or window. Since that will disable all addons, and other browser functions that can skew results when testing performance and paints.

 

It is always best to sometimes add a slight rotation when translating x, y, or z for smoother translation due to browser bugs, Plus that will allow the browser to use matrix3d(). You never added my advice to add rotation:0.01 on your tweens. When i do that i see transform on the inline style use matrix3d() instead of translate3d() and the translation becomes much smoother.

 

See the Pen GjWRPa by jonathan (@jonathan) on CodePen

 

It looks smooth to me.. tested on Window 7 and Windows 10 latest Chrome 53.

 

Also you might want to keep in mind that Chrome 53 has a old new bug that could also be affecting your background-image.

 

http://greensock.com/forums/topic/13875-chrome-49-janky-gsap/

 

And you also might want to add a parent with position relative, so your absolutely positioned element has a parent that it is relative to. As a rule of thumb that helps with cross browser layout, so your not animating absolutely positioned elements without having position relative, an anchor point.

 

:)

 

 

 

Anytime you are testing performance in Google Chrome, you must use a new incognito mode tab or window. The Google Dev team recommend that you always test performance, paints, and frame timeline in a incognito mode tab or window. Since that will disable all addons and not skew results when testing performance and paints.

Link to comment
Share on other sites

If I'm understanding the issue correctly your main goal is to minimize the amount of layer creation that happens when animations start playing.

If you have the ability to create the animations before you need them to play it might help to 

 

1: set force3D to true which will keep the assets layerized in case you need to replay the animations and avoid the re-layerizing on subsequent plays

2: instantly set the animation's progress to 1 and then back to 0 (which will force everything to layerize)

 

CSSPlugin.defaultForce3D = true;


var testCube = document.getElementById("testcube");
var animation = TweenMax.to(testCube, 1, {x: 1000, paused:true});
animation.progress(1).progress(0); // layerize everything


function start(){
    animation.play();
};

 

Does this example work better for you: http://codepen.io/GreenSock/pen/YGkXQN?editors=0110

 

What's nice is that you can apply this technique to massive timelines and get the same benefits.

  • Like 2
Link to comment
Share on other sites

Nice Carl ;) .. I forgot about offering the .progress(1).progress(0) technique for pre-caching the timeline properties and layer creation :)

  • Like 1
Link to comment
Share on other sites

Right now i'm sitting in front of PC (GTX 750TI + i7). And of course it runs smooth. Can't be any smoother. But To my right side I have an LG TV, which hardware is much less perform-ant, and for what I have to develop. And the LAG is there and it's very annoying. It's there every time new layer is written to video memory. This can't be a clear GSAP problem, and I'm not telling that. I just wanted to start a brainstorm, hear and speak out ideas and suggestions. 

Link to comment
Share on other sites

Carl. Yes. That's was kind of my point.  What is the drawback of your strategy, that you kind of can't know when all stuff is layerized. Especially when it's a lot. 

Link to comment
Share on other sites

Carl. And doesn't work for ex. like this 

See the Pen ORpLKB by anon (@anon) on CodePen

. Having layer, inside transformed layer is even a larger performance hit. So I will have to do this smart, and layerize in right time and place (better when nothing moves). 

Link to comment
Share on other sites

Does that LG TV have a game mode on it? That would force the TV to be 60fps = 60Hz.

 

TV's won't match the same screen refresh rate of computer monitors without a game mode for 60Hz. But also consider on a TV that there 'might' be screen tearing (stutter) even if the TV supports 60Hz.

 

Note: I fixed the topics title for you :)

  • Like 1
Link to comment
Share on other sites

It's an commercial TV. Kind of you can program it to run same app or web page on start, has additional JS calls to control the TV options, etc,. Not standard with TV channels and smart features. The refresh rate is fine. The problem is with its GPU bandwidth. Anytime (or, at time) a a new layer is pushed to VRAM, rendered can't handle stable performing. 

Link to comment
Share on other sites

And I think I know what to do, and the limitations. Thanks guys for input very much. GSAP team rocks's :))

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×