1

I’m having a strange issue with a fairly complex ThreeJS scene. I’ve spent a few days moving the entire 3D scene to an offscreencanvas and I’ve moved the loading of my GLB files and texture maps to a web worker. This all works and I’m able to render the scene and it all looks the same as it did before, when I had a traditional canvas element.

However, I have a loading spinner on my page and after all the assets have loaded and I render the scene, the spinner starts janking. I’ve tried adopting a method where all my 3D objects are invisible and I reveal them one at a time, on each iteration of the render loop until they are all visible, and I can clearly see my spinner is becoming janky when the scene renders some glass objects with reflections on. I saw this same behaviour before, with the traditional canvas so I guess this is an intensive undertaking for the renderer.

But why am I seeing this jank on the main thread!? I’ve had a look through Chrome’s Memory tab but I must confess I don’t really know what I’m looking at in there. I can’t share a demo, unfortunately because the project is commercially sensitive and still in R&D, but can anyone shed any light at all on what on earth is happening please? Or perhaps point to me how I might be able to see separate memory threads in Chrome’s dev tools? Perhaps my web worker has simply max’d out its thread?

Thanks so much for any pointers

EDIT:

@Kaiido Loading the GLB and image files is now faster and has no effect on the main thread, so using the web worker isn't entirely for nothing.

Here is a screen grab of Chrome's Performance tab, but to be honest I don't really know what I'm looking at! :

enter image description here

and here's what I see when I type about:gpu:

enter image description here

So I guess it really is just the demands I'm putting on the Graphics Card? At the end of the day, I have a fairly complex 3D character with skeleton animations and facial morphs in an office environment, but I've already spent weeks reducing the sizes of my texture maps, changing to the simplest 3D material types in ThreeJS and massively optimising my animation frames. I don't know what more I can do! And I'm also revealing as single 3D object at a time so that the renderer can take a breath in between initialising each one.

Is there really no way to use the separate memory threads available on my GPU? :o(

enter image description here

1 Answers1

2

The Web-Worker + OffscreenCanvas setup will allow to move all the CPU work on a concurrent thread.

But the GPU work is still done on a single GPU process. So if your GPU process is locked by one of the threads, the other one will also be locked, even if the CPU thread is actually free.

You can check your dev-tools's Performance tab to check exactly where's the bottleneck in your app, and if indeed it's in the GPU thread that it locks.
One long-shot workaround could be to force your spinner to use software acceleration instead of GPU acceleration. Not seeing how it's done currently it's hard to tell what you should change, but you can start a deaccelerated 2D canvas doing canvas.getContext("2d", { willReadFrequently: true }) and you can probably use that 2D context do implement your spinner.

Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • Thanks so much for your response, @Kaiido. My spinner was just an example of the jankiness on the main page. I also animated a red div moving up and down the page using `gsap` and it exhibited the janky behaviour. Since posting, I've tested the page on some other browsers: On my Windows PC, I see the jankiness in Chrome and Brave (also Chromium), but its silky smooth on Firefox. On MacOS , it's smooth on all browsers, including Brave. So I wonder if it's related to this bug: https://bugs.chromium.org/p/chromium/issues/detail?id=1076349 whose status is sadly `WontFix`. – GeorgePorge May 30 '23 at 14:31
  • Hehe funny, I did report that bug :-) And no, I doubt it's related, this concerns only the initialisation of the Worker. Once it got access to the compositor, everything is as usual. Once again, check the perfs tab of your dev-tools and see where it really blocks. I stand on the GPU thread, moreover if you can't repro on FF. You can also try to disable Hardware Acceleration in your Chrome's settings to confirm. – Kaiido May 30 '23 at 21:10
  • Ha! That was your bug report? Weird :o) I had a look at the performance tab in Chrome and I can see there are a lot of purple coloured functions that take way longer than 16.7ms to run and I see lots of dropped frames. But I'm not very familiar with the info here and I don't really know what I am looking at - how much GPU memory is available and how much of that I'm using. Disabling hardware acceleration in Chrome did indeed stop the janking when the render kicked in. So where does this leave me? The janking is apparent on scrolling the page, not just my spinner and animated div. Am I screwed? – GeorgePorge May 31 '23 at 08:47
  • So that confirms what I put in this answer: your graphic card is the culprit, and indeed in that case going through a Web Worker won't help. So we have to go back a bit and get why it's so hard on the graphic card. On this I might not be the best to help you, but you can still share a screenshot of your perfs tab, and maybe also of your `about:gpu` page (mainly the top "Graphics Feature Status" section). – Kaiido May 31 '23 at 08:57
  • Thanks @Kaiido, I've edited my original post with some more info. – GeorgePorge May 31 '23 at 09:50