mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
102.39k stars 35.35k forks source link

Jank with trivial scrolling animation #21088

Closed steve-o closed 3 years ago

steve-o commented 3 years ago

Describe the bug

Jank appears in 60fps animation in Chromium based browsers on desktop and embedded devices. System traces appear to show frames rendering but the Chromium Team suggest HTML rasterization is happening, with that being the root cause of the jank.

Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=1164435#c7

Jank is not visible on an AMD Ryzen 9 3950X with nVidia Quadro RTX 4000.

To Reproduce

Visit page hosted, or downloaded.

Live example

Expected behavior

Smooth 60fps animation, as per running on desktop with nVidia RTX 4000 or similar.

Screenshots

"JavaScript and Rendering" trace shows a section of jank reported beneath periodic frame callbacks from RequestAnimationFrame(). This may be a misreading of the chart.

image

Platform:

mrdoob commented 3 years ago

System traces appear to show frames rendering but the Chromium Team suggest HTML rasterization is happening, with that being the root cause of the jank.

How's that possible? The page only has a <canvas> element.

mrdoob commented 3 years ago

Also, I'm unable to reproduce on an Intel MacBook Pro from 2016.

mrdoob commented 3 years ago

Can you share a video recording of your screen showing the jank?

steve-o commented 3 years ago

On the nVidia Shield Pro it is more apparent, but in this clip it happens a few times on the MacBook Air:

https://www.youtube.com/watch?v=Y20nRBpd7aw

See ~2s, ~4s, ~5s, ~7s, for dropped frames.

It usually runs for longer periods of time with no jank whatsoever, i.e. 10-20s. I had to reshoot the video at 60fps because the dropped frames do not appear at 30fps.

mrdoob commented 3 years ago

Can you do another video with Firefox and another one with Safari?

steve-o commented 3 years ago

Some GC at the beginning, which is acceptable, on replay I see the jank at similar timepoints though.

Firefox: https://www.youtube.com/watch?v=JEcIED7_-X0

Safari: https://www.youtube.com/watch?v=ffuXgB8ceYM

steve-o commented 3 years ago

For record, the nVidia Shield Pro: https://www.youtube.com/watch?v=vRjynafm6E4

nVidia RTX 4000: https://www.youtube.com/watch?v=SvGWB8Lovgw

Apologies that the phone isn't really capturing very well.

mrdoob commented 3 years ago

Can you try not using delta? Just const deltaX = SPEED;

steve-o commented 3 years ago

I changed to const deltaX = SPEED * 16.667; for the same velocity, and the jank still remains, it does not appear related to the clock (also verified across the different browsers).

http://ahyoomee.miru.hk/test/www/q.html

steve-o commented 3 years ago

FYI: The MSDF shader and code are from https://github.com/Jam3/three-bmfont-text, the files upstream don't include any attribution.

mrdoob commented 3 years ago

Lets take MSDF out of the picture. Can you simplify your test case to just cubes?

Mugen87 commented 3 years ago

I have such minor random stuttering on my iMac with all WebGL applications. It happens very infrequent but even with very basic WebGL scenes (e.g a single triangle translated along the x axis).

This is definitely unrelated to three.js. It also happens only with Chrome, not with Firefox and Safari. Unfortunately, I don't see something unusual in the performance analysis tool.

TBH, I've never experienced this as disturbing hence I've never reported this to the Chromium issue tracker.

mrdoob commented 3 years ago

Yeah. Same here.

It just becomes more evident when you do scrolling text like in this test case.

I'm just trying to help @steve-o to remove ambiguity from the test case so Chromium devs know where to look.

steve-o commented 3 years ago

Ok, will update.

FYI: This simple scrolling is used on the NYSE trading floor, however the implementation currently running there is using PIXI.js instead of THREE.js. Just reviewing the videos of when people were allowed on the floor found this one, which also has a jump in scrolling. That is Chrome on Ubuntu with Quadro p1000's.

https://youtu.be/DS2BrFvSUa8?t=48

Mugen87 commented 3 years ago

I think I also see the stuttering on a Windows gaming laptop with a 144 Hz screen and Chrome. Because of the high frame rate, the issue is more subtle. But I believe it's there.

Interestingly, the stuttering does not appear in Edge.

Mugen87 commented 3 years ago

Damn, not that I focus on it it's somewhat annoying...

steve-o commented 3 years ago

Ok, replacing MSDF text with simple square geometries with colour fill. This also exhibits jank, maybe needs a UFO to match https://testufo.com/ 😆

http://ahyoomee.miru.hk/test/www/qq.html

Updated bundle for download: https://drive.google.com/file/d/1eWBU5rhA7Vu9S3FohknMuZuMAs_UXO2C/view?usp=sharing

Mugen87 commented 3 years ago

Do you see stuttering in this demo? https://jsfiddle.net/9be53fnt/

steve-o commented 3 years ago

Yes, on both Chrome, Firefox, Safari, and Android.

Fullscreen version: https://ahyoomee.miru.hk/test/www/b.html

kenrussell commented 3 years ago

Note that the JSFiddle harness itself can be introducing a lot of complexity, so standalone tests are best.

I see stuttering on https://ahyoomee.miru.hk/test/www/b.html in both Chrome and Firefox on macOS (dual-GPU 2017 MacBook Pro), and also on Android on both browsers.

Grabbing Chrome's about:tracing "Javascript & rendering" trace on macOS, the janks still seem to be associated with HTML rasterization. Assuming this is not doing anything strange behind the scenes, it's a mystery why that would be happening.

If you can eliminate even the Three.js dependency then maybe this can be classified as a browser bug. https://github.com/KhronosGroup/WebGL/pull/3183 is a recent WebGL conformance test case that animates a square; you could extract the associated shaders and buffer setup.

kenrussell commented 3 years ago

Command line used to launch Chrome Canary on macOS, to eliminate as many additional dependencies as possible:

/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary --user-data-dir=/tmp/c1 --use-cmd-decoder=passthrough --disable-extensions

This uses Chrome's newest code path for WebGL (ANGLE + the "passthrough" command decoder).

RemusMar commented 3 years ago

https://ahyoomee.miru.hk/test/www/b.html

Very smooth motion but horrible glitches every 10-15 seconds. Windows 10 (latest updates), Core i7, GTX 1060, both Firefox and Chrome browsers.

RemusMar commented 3 years ago

Here is something very strange I didn't notice in the past 3 years: https://necromanthus.com/Test/html5/SMC.html Keep the mouse either in the left or the right side and wait. The rotation is very smooth, but I get the same horrible glitches every 10-15 seconds. For me this looks like BUGGY browser updates! I have no idea how old is this issue ....

steve-o commented 3 years ago

The jank is not really a unique artifact of WebGL, as similar jank appears with CSS keyframes and WebAnimations. However one hoped WebGL without the overheads of DOM would bypass any major overheads the browser incurs. You can still see similar issues with OffscreenCanvas and even the prototype THREE.WebGPURenderer.

Well, here is my first raw WebGL app ever, it should be similar to the example from @Mugen87

http://ahyoomee.miru.hk/test/www/gg.html

I stuck with WebGL2 as less confusing on the shaders for me.

kenrussell commented 3 years ago

Thanks @steve-o for the significantly reduced test case. I've updated the Chromium bug you filed http://crbug.com/1164435 with some initial analysis.

On my Mac, Safari seems to perform the best, followed by Chrome, followed by Firefox. Also seeing significant jank on Android.

A couple of thoughts. @mrdoob is Three doing its framerate measurement even when the visualizers aren't visible? That might explain the HTML rasterization in the Three.js version of this simple test case.

Submitter, I also think you should do time-based rather than tick-based animation. Dropped frames should be much less visible then. Could you try that?

steve-o commented 3 years ago

I added the time delta code, forgot to use it for movement. Instead of replacing, I'll just add another version:

http://ahyoomee.miru.hk/test/www/ff.html

mrdoob commented 3 years ago

@steve-o

The jank is not really a unique artifact of WebGL, as similar jank appears with CSS keyframes and WebAnimations.

Do you have a test case for that too?

I guess that would make this a browser compositor issue rather than WebGL?

mrdoob commented 3 years ago

@kenrussell

A couple of thoughts. @mrdoob is Three doing its framerate measurement even when the visualizers aren't visible? That might explain the HTML rasterization in the Three.js version of this simple test case.

I think you're referring to the stats.js widget? That widget is not included in three.js.

steve-o commented 3 years ago

Do you have a test case for that too?

These are from 2014, with the WebAnimations polyfill being completely obsolete now and incompatible with the modern API. Updated versions would be more suitable.

CSS animations, GPU accelerated: https://miru.hk/tmp/nyse/txt/gpu.html WebAnimations, ~2012 polyfill: https://miru.hk/tmp/nyse/txt/carousel3.html

You can still see the jank though 🙃

Of note nVidia's GeForce Now page uses CSS animations to scroll through their hosted titles: https://www.nvidia.com/en-us/geforce-now/ and Apple has started to use the modern WebAnimations API on their site: https://www.apple.com/tv/

RemusMar commented 3 years ago

I've updated the Chromium bug you filed http://crbug.com/1164435 with some initial analysis.

For me it's not a "jank" and I don't get it in Edge (on Windows). I get it in Firefox and Chrome only. It's a kind a glitch (freeze for 0.1-0.2 seconds) every 5-10 seconds. So again, I think it's a buggy browser update (probably ANGLE / GC related) somewhere in the past and never fixed.

RemusMar commented 3 years ago

Here is a simple Canvas 2D animation: https://necromanthus.com/Test/html5/3Dcanvas.html

Results on my machines: 1) Firefox: the same glitches (freezes) every 5-10 seconds 2) Chrome: your "jank" (LOL) 3) Edge: no issues at all

The bottom line: this "jank" issue has nothing to do with THREE.js

kenrussell commented 3 years ago

@steve-o : on my machine (2017 MacBook Pro), http://ahyoomee.miru.hk/test/www/ff.html runs pretty smoothly in Chrome. It looks like it drops perhaps 1 frame every 4 left-to-right iterations. Fewer in a fresh browser instance - I usually have 30+ tabs open. Microsoft Edge Canary on Mac has the same behavior - as expected, because it's using the same Chromium engine as Chrome does.

We can certainly still investigate that test case - it's unfortunate that the browser can't do such a simple animation smoothly.

Is there any other simplified text based case - or slightly more complicated case - showing more dropped frames that we can look into?

RemusMar commented 3 years ago

@kenrussell

I usually have 30+ tabs open

That's a bad thing to do even if you have a Core i9 CPU and 64GB memory. Always use a single browser window (and tab) when you benchmark something.

Anyway, as I said before, this "jank" issue has nothing to do with THREE.js I tried with various (very simple & very complex) samples in Chrome, Firefox and Edge. cheers

steve-o commented 3 years ago

@kenrussell , I think we're so far good on Windows, Linux, and ChromeOS. The Chromium team need to focus on Android's WebView for continuous jank and MacOS for the sporadic jump. The full ticker implementation on the initial ticket works fine on an i3 ChromeBox, so it's only these platform specific issues.

If one goes by the description on https://jankfree.org, both scenarios fall under the umbrella of jank, but so far have nothing direct to do with THREE.js, (or PIXI.js)

Jank is any stuttering, juddering or just plain halting that users see when a site or app isn't keeping up with the refresh rate.

If anyone wants to verify against a more complicated ticker that is used in production, try this, ignoring the initial loadout lag and relayout.

http://ahyoomee.miru.hk/zignage/ticker.html

steve-o commented 3 years ago

Verified reasonably happy for ff.html on a 2010 MacMini with GeForce 320M running Windows 10 via BootCamp.

steve-o commented 3 years ago

It appears Linux is possibly in the same camp as MacOS here, from systems running Ubuntu and OpenSuSe with AMD or nVidia GPUs. However contradictory reports exist highlighting no problems.

It would be interesting to know whether these also due to the same OpenGL issues on MacOS, and whether the shift over to Vulkan would also be the long term resolution. I see that experiments for Vulkan support started in Chromium 79.

kenrussell commented 3 years ago

Thanks for your continued investigation @steve-o .

The original test case for this bug http://ahyoomee.miru.hk/test/www/n.html is definitely doing enough additional work that the stuttering in its animation is caused by more factors than your ultra-simple WebGL 2 test case http://ahyoomee.miru.hk/test/www/ff.html - which can not be explained as anything else than poor browser behavior.

Without your diving into the dependent text rendering code of http://ahyoomee.miru.hk/test/www/n.html , I don't think the Three.js team is going to be able to postulate some optimization that will eliminate the additional stuttering.

In sum, I agree that this bug should be closed, and investigation should continue on http://crbug.com/1164435 - and on any other bugs that are filed against any other browsers that don't achieve smooth animation of that test case.

steve-o commented 3 years ago

The text rendering is all on the GPU, via vertex and fragment shaders for MSDF, so anything there affecting the animation performance would be some issue of the browser too. The custom geometry and setup is a one-off cost and should not be relevant. Closing, whilst waiting to see any feedback from Android and other teams.