apache / cordova-ios

Apache Cordova iOS
https://cordova.apache.org/
Apache License 2.0
2.15k stars 987 forks source link

WebGL performance significantly slower since iOS 15 #1246

Open Kosmoon opened 1 year ago

Kosmoon commented 1 year ago

Problem

Same game built with phaser is running at 60 fps on iOS 14 and 30 fps on iOS 15

it seems that it's due to an experimental feature set to "on" by default in 15.x: "GPU Process: Canvas Rendering", ref: https://developer.apple.com/forums/thread/684843

is there a way to change experimental features of wkWebview ?

breautek commented 1 year ago

I'm not well knowledgeable in this area, but thought I'd give a response since no one else did over the weekend.

I'm fairly confident the experimental flags are not programmable. I've found several sources indicating that it can be changed using the Safari settings, but in every instance there was a mixture of complaints on people using the actual Safari browser vs people using WKWebView so it's unclear if that actually works for embedded WKWebview. It's not even clear if that even applies to iOS WKWebview. But I guess it's worth a try?

I'll leave this ticket open for someone else that is more knowledgeable. Alternatively, you can try asking our Slack Community as well.

erisu commented 1 year ago

You might want to try the following to see if it helps you out in anyway.

Note, that the code is loading an external library for platform identification. platform.js which I have not tested or reviewed.

If you are already using any pre-existing plugin or library that can identify the browser/device/version, then I would suggest modfying the code to use that instead.

I added a comment to the top of the source code with the link to where it originated from.

<!-- Code Original Source: https://github.com/flutter/flutter/issues/89655#issuecomment-936666189 -->
<!-- iOS 15 WebGL 2.0 fix (https://github.com/flutter/flutter/issues/89655) -->
<!-- TODO(your_username): Remove when https://github.com/flutter/engine/pull/29038 will be merged to stable -->
<script src="https://unpkg.com/platform@1.3.5/platform.js"></script>
<script type="text/javascript">
function isIOS() {
  return [
    'iPad Simulator',
    'iPhone Simulator',
    'iPod Simulator',
    'iPad',
    'iPhone',
    'iPod'
  ].includes(navigator.platform)
  // iPad on iOS 13+ detection
  || (navigator.userAgent.includes("Mac") && "ontouchend" in document)
}

if (isIOS() && parseInt(platform.os.version.split(".")[0]) >= 15) {  
  // iOS/iPadOS 15+
  HTMLCanvasElement.prototype.getContext = function (orig) {
    return function(type) {
      return type !== "webgl2" ? orig.apply(this, arguments) : null
    }
  }(HTMLCanvasElement.prototype.getContext)
}
</script>
Kosmoon commented 1 year ago

You might want to try the following to see if it helps you out in anyway.

Note, that the code is loading an external library for platform identification. platform.js which I have not tested or reviewed.

If you are already using any pre-existing plugin or library that can identify the browser/device/version, then I would suggest modfying the code to use that instead.

I added a comment to the top of the source code with the link to where it originated from.

<!-- Code Original Source: https://github.com/flutter/flutter/issues/89655#issuecomment-936666189 -->
<!-- iOS 15 WebGL 2.0 fix (https://github.com/flutter/flutter/issues/89655) -->
<!-- TODO(your_username): Remove when https://github.com/flutter/engine/pull/29038 will be merged to stable -->
<script src="https://unpkg.com/platform@1.3.5/platform.js"></script>
<script type="text/javascript">
function isIOS() {
  return [
    'iPad Simulator',
    'iPhone Simulator',
    'iPod Simulator',
    'iPad',
    'iPhone',
    'iPod'
  ].includes(navigator.platform)
  // iPad on iOS 13+ detection
  || (navigator.userAgent.includes("Mac") && "ontouchend" in document)
}

if (isIOS() && parseInt(platform.os.version.split(".")[0]) >= 15) {  
  // iOS/iPadOS 15+
  HTMLCanvasElement.prototype.getContext = function (orig) {
    return function(type) {
      return type !== "webgl2" ? orig.apply(this, arguments) : null
    }
  }(HTMLCanvasElement.prototype.getContext)
}
</script>

Thank you for taking the time to answer to me. Unfortunately this doesn't fix the problem on my side. Webgl context is never using webgl2 on my testing setup so the issue is not caused by webgl2

breautek commented 1 year ago

Is it possible to test this in the real iOS Safari browser to determine if the issue also happens in the browser app?

If the issue is not exclusive to WKWebView, then it would suggest that the issue is deep in the browser engine, and it's likely nothing that Cordova can do about it.

I think you can also test your theory on GPU Process: Canvas Rendering because I do believe you can enable/disable experimental features on the iOS safari browser app. If you can reproduce your issue in the browser app, but fix it by disabling the Canvas Rendering experimental feature, then you have strong evidence that says the issue is indeed the Canvas Rendering feature. But if that is the case, then I think you're out of luck because from my own Google searching, enabling or disabling experimental features doesn't appear to be possible with WKWebView. On the other hand, there's a comment indicating that experimental features do not have any effect on the webviews, just the browser app.