Bug 232271

Summary: REGRESSION (iOS 15): Fragment shader performance is several times worse
Product: WebKit Reporter: Brian Richardson <brichardson>
Component: WebGLAssignee: Nobody <webkit-unassigned>
Status: NEW ---    
Severity: Normal CC: 3dsrdlab, dino, kbr, kkinnunen, kpiddington, sebastien.videcoq, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: All   
OS: Unspecified   
Bug Depends on:    
Bug Blocks: 231180    
Attachments:
Description Flags
Test case showing the issue. If you run with /?num=6 you'll see the perf cliff vs /?num=5
none
another test case
none
Workaround demonstrating how uniform data type affects performance none

Description Brian Richardson 2021-10-25 14:28:16 PDT
We've noticed a performance regression when having a lot of work inside of a fragment shader. I happened to have an iPad Air (3rd gen) that was still on iOS 14 so I could do a proper test.

I reproduced it with a small Three.JS testbed:

iOS15, iOS14, Test
60, 60, https://depot.knowhere.net/ios15regression/?num=5 
6, 55, https://depot.knowhere.net/ios15regression/?num=6
4, 33, https://depot.knowhere.net/ios15regression/?num=10

I see the same cliff at num=6 with my iPhone 12 Pro.  

Normally, I'd just say that's the perf cliff and call it good.  But it's odd that it's changed so much between 14 and 15, maybe something can be done?
Comment 1 Kimmo Kinnunen 2021-10-25 23:36:03 PDT
Thank you for the report. If you have time, a test case where three.js and the payload app code is unbundled and both are not minified would be most useful. 

I can reproduce the issue. Reproduces also on macOS, AMD. The GPU work increases very much when using ANGLE Metal backend.
Comment 2 Brian Richardson 2021-10-26 11:21:38 PDT
Hello Kimmo:

Thanks for taking the time to look into this.  I've updated the example to use just vanilla HTML/JS and an external version of Three.JS. I hope that makes things easier!
Comment 3 Radar WebKit Bug Importer 2021-10-26 17:30:41 PDT
<rdar://problem/84688595>
Comment 4 Kimmo Kinnunen 2021-10-27 06:03:04 PDT
(In reply to Brian Richardson from comment #2)
> Hello Kimmo:
> 
> Thanks for taking the time to look into this.  I've updated the example to
> use just vanilla HTML/JS and an external version of Three.JS. I hope that
> makes things easier!

Thanks!
The update does not seem to work on Safari?

"[Error] TypeError: Module specifier, 'three' does not start with "/", "./", or "../". Referenced from https://depot.knowhere.net/ios15regression/?num=5
	promiseReactionJob"

(It does work on Chrome, though..)
Comment 5 Brian Richardson 2021-10-27 10:35:46 PDT
(In reply to Kimmo Kinnunen from comment #4)

> The update does not seem to work on Safari?

Fixed. I thought it'd be a fun time to try import maps, I guess when I tested on my phone it was using a cached version.  Removed that and it works in Safari for me!
Comment 6 Brian Richardson 2021-10-27 10:36:53 PDT
Created attachment 442606 [details]
Test case showing the issue.  If you run with /?num=6 you'll see the perf cliff vs /?num=5
Comment 7 Sébastien VIDECOQ 2021-11-24 10:10:56 PST
Hello, any progress on this bug ? 
It deeply impacts our product, FPS has dropped from 60 to 2 FPS.

Adding another test sample that illustrate the behavior.
Thanks in advance.
Comment 8 Sébastien VIDECOQ 2021-11-24 10:12:17 PST
Created attachment 445098 [details]
another test case
Comment 9 Brian Richardson 2021-11-24 11:39:08 PST
Sébastien:

In our case, manually unrolling the loop seems to work around the issue. Give it a shot! Hope that helps!

Brian
Comment 10 Sébastien VIDECOQ 2021-11-24 11:53:24 PST
Brian, thanks a lot for the advice, we already gave a quick try this afternoon, but we are far from getting back performances of iOS 14. Maybe we are now facing  another iOS 15 regression ? We will try again tomorrow and provide feedbacks.
Comment 11 Kyle Piddington 2022-01-18 12:59:50 PST
Hi all! Some updates for you. Apologies for the delay.

We've identified the main issue here. Part of our shader transformation passes tries it's best to preserve the original GLSL struct while following Metal alignment best practices. 

What this means for the attached shaders is that we're promoting the vec3 uniforms to vec4 for sending over as uniform data, but are then converting back to vec3 in the MSL shader. This temporary variable is able to be stored in shader registers, up until the arrays get too big. 

We'll have a fix in on our end, but if you need faster performance in the meantime, try changing your vec3 variables to vec4.
Comment 12 Kyle Piddington 2022-01-18 16:54:18 PST
Created attachment 449452 [details]
Workaround demonstrating how uniform data type affects performance