model-viewer
model-viewer copied to clipboard
iOS 17 Safari Privacy Protections slows down rendering with multiple model viewers on page
Description
Well this is fun. Safari in iOS17 and Sonoma introduced "Advanced Tracking and Fingerprinting Protection". This is on by default in private tabs. It seems to throttle the renderer (or at least canvas operations) in order to prevent device fingerprinting.
This article is light on details, but includes the line
Lastly, Advanced Privacy Protection will add ‘noise’ into several key fingerprinting vectors, such as 2D Canvas, Web GL, Web Audio and Screen a& Window geometry.
Live Demo
Desktop
- In Safari (on OSX Sonoma) open a private tab and go to https://adhesive-hypnotic-pantry.glitch.me
- Rotate the astronaut around (it will be sluggish)
- Go to View ->
Reload reducing private protections
- The page will reload, now rotate the astronaut and it will be normal performance
Mobile
- In Safari (in iOS 17) open a private tab and go to https://adhesive-hypnotic-pantry.glitch.me
- Rotate the astronaut around (it will be sluggish)
- You can turn off privacy protections in General -> Safari -> Advanced -> Advanced Tracking and Fingerprinting Protection
- Reloading the page will have normal performance again
I even get this popup sometimes
The same behaviour can be seen on sites that have multiple canvas elements. Ex, this one is written in vanilla webgl (not three): https://ciechanow.ski/bicycle/, and the issue shows.
This behaviour is not present on sites that have a single canvas it seems. For example, this works fine: https://model-viewer.glitch.me. And the threejs example of using a single canvas and scissor cutting out multiple scenes also works fine: https://threejs.org/examples/?q=multiple#webgl_multiple_elements
It seems like it starts getting sluggish after three or some canvas elements. I need to investigate further, but really not sure what a fix could be here.
Version
- model-viewer: v3.3.0
Browser Affected
- [ ] Chrome, version: xx.x.xxxx.xx
- [ ] Edge
- [ ] Firefox
- [ ] IE
- [x] Safari
OS
- [ ] Android
- [x] iOS (17)
- [ ] Linux
- [x] MacOS (Sonoma)
- [ ] Windows
So it seems like if each canvas has its own webgl context, then it's fine. Example: React-three-fiber scene with multiple separate canvases: https://pydwvq.csb.app That is smooth with or without the protection on.
So I'm led to believe it's likely the canvas2D drawImage
operation that is the root issue with model viewer and other apps that share a single webgl context across canvases
Oh interesting, I guess drawImage
if there's only one of the page. That must explain why it renders just fine with one model viewer
Indeed, this is one of our key performance features. Sharing the context is dramatically more efficient for both loading time and GPU RAM usage, but we save a copy when there's only one canvas (which is pretty common). I think Apple's getting a major false positive here - have you reported a WebKit issue yet? @grorg in case he can escalate this inside Apple.
Just filed it here: https://bugs.webkit.org/show_bug.cgi?id=266181
I made a minimal test case too: https://glitch.com/edit/#!/evanescent-traveling-radio?path=index.html%3A84%3A0
Can confirm this is fixed in iOS 17.4 following the resolution of: https://bugs.webkit.org/show_bug.cgi?id=266181
Thank you for helping to get that resolved!
FYI - I don't work on this project within Apple any more, which I why I haven't been replying to pings. Sorry. (cc @elalish)
@grog, thanks for letting us know. Any other Apple Github handle we can ping instead?