phaserjs / phaser

Phaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
https://phaser.io
MIT License
37.22k stars 7.1k forks source link

Memory leak rendering to larger resolutions on iOS (3.85.x) #6914

Closed mikaleerhart closed 1 month ago

mikaleerhart commented 1 month ago

Version

Description

I followed this tutorial the other day when porting the game I'm working on to mobile. I compiled and ran their example game rendered to the native resolution by calculating window.innerWidth * window.devicePixelRatio by window.innerHeight * window.devicePixelRatio. Using Capacitor, the tutorial game ran just fine at that resolution on all devices I tested (I have various iPads, iPhones, and Android devices). But when I tested my game it ran fine on everything but iOS, specificially devices with a screen resolution of larger than ~2200px high (I tested by rendering my game to specific sizes up until the leak appeared). The page would continuously crash and reload, and in Xcode, this is the error I'm getting: Screenshot 2024-10-04 at 11 12 47 AM The error only happens on the physical device, my game ran in the simulator.

My game runs fine on iOS in Phaser v3.85.x at lower resolutions than mentioned above. I couldn't figure out why the example game ran without error at full resolution and mine did not, so eventually I tried switching to the version of Phaser used in the tutorial, v3.80.1 and the error went away and my game rendered at the full resolution. I've never looked deeply into the source code of Phaser but I've been scratching my head over this for some time now and finally got to the bottom of it, so I figured I'd report this.

Example Test Code

Additional Information

DavidTalevski commented 1 month ago

This issue is not limited to iOS, this also happens on android and is a very serious problem. Specifically the same game running on a Samsung Galaxy A14, rendering on 1080 x 2408, on phaser version v3.80.1 runs smoothly with no issues and on version v3.85.0 and above it crashes upon startup. The only way I could get the game to start on v3.85.0 while I was testing why this happens was giving the game config a smaller resolution upon creation, then changing the game resolution to 1080 x 2408 using setGameSize in the scale manager but this was no workaround since the game ran horribly (especially when having to create new objects) and crashed after a minute of playing. I will have to start looking on all the changes that happened in 3.85.0 that introduced this problem, I'm pretty sure it has something to do with the WEBGL changes since starting the game in CANVAS works.

photonstorm commented 1 month ago

There were next to no changes made in the renderer between 3.80 and 3.85 - beyond removing the round pixels shader code and moving the context loss handler function. I suspect that's a red herring and the real cause is something else. If anyone can provide private access to a test project that demonstrates it, it would certainly speed-up the investigation.

DavidTalevski commented 1 month ago

I believe this https://phaser.io/sandbox/y1pmMkDL demonstrates it if you change the resolution of the game. This issue isn't connected to capacitor or cordova since I ran this sandbox on the Samsung Galaxy A14, I changed the resolution of the game to 1080x2400 and on v3.85.0 it crashed the entire browser and on v3.80.1 it runs perfectly. I will check and see what's happening with the memory usage and I'll update you.

DavidTalevski commented 1 month ago

image_2024_10_07T11_23_16_805Z I got these logs before it crashed the browser.

mikaleerhart commented 1 month ago

To reproduce:

  1. I downloaded this code and installed deps: https://github.com/phaserjs/starshake-capacitor-tutorial
  2. I changed phaser to 3.85.2 in package.json and reinstalled phaser.
  3. npm run build npx cap copy and run on iOS. That's it. the page won't render and just keeps reloading. Here's my Output: Screenshot 2024-10-07 at 10 45 59 AM

If you change the game to a lower resolution (I just did 640x480) in 3.85.2, the game will render.

It happens in my game too. Same issue in both Cordova and Capacitor. Also tested it on iOS 17.6 vs. 18 to see if it was Safari, and same issue. The game only renders when I downgrade phaser.

photonstorm commented 1 month ago

Yeah I know what causes this - it's the RenderTextures. Under 3.80.1 it created them in various sizes (in steps of POT) up to the canvas size, but under 3.85 for some reason they're all canvas sized, so it's basically just running out of memory, and that's what browsers do when they run out of memory, they close down.

Am working on a fix now, will be in 3.85.3 release.

mikaleerhart commented 1 month ago

Thank you!

photonstorm commented 1 month ago

If you want to resolve it in the meantime, and if you don't use any PreFX in your game (like Bloom, Glow, etc i.e. the built-in FX), then set:

disablePreFX: true

in your game config and it will use dramatically less GPU memory by default.

photonstorm commented 1 month ago

Thank you for submitting this issue. We have fixed this and the fix has been pushed to the master branch. It will be part of the next release. If you get time to build and test it for yourself we would appreciate that.