godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.92k stars 20.16k forks source link

Poor mobile performance on HTML5 export #58836

Open rafaelcastrocouto opened 2 years ago

rafaelcastrocouto commented 2 years ago

Godot version

v3.4.2.stable.official.45eaa2daf

System information

Windows 10, GLES2, NVIDIA GeForce 940M

Testing on recent Android and Iphones

Issue description

Exporting a game with a couple of tiles and a camera results in renders of 30 FPS and lower

Seems like there's something wrong since I've tryed all optimizations recommended on the latest tutorials and still weren't able to get decent performance.

Steps to reproduce

Create a new project add some tiles and a camera, export to HTML5 and check the frame rate.

Minimal reproduction project

https://github.com/rafaelcastrocouto/godot-web-fps

godot-web-fps-main.zip

rafaelcastrocouto commented 2 years ago

I just checked that it is happening in Chrome and Brave browser.

Calinou commented 2 years ago

HTML5 gaming on mobile browsers has always been a contentious issue, especially in 3D. I don't think it's possible to get something as smooth as a native application, simply due to the WebAssembly and WebGL overhead.

Which Android and iOS device models did you test this on? Consider rendering at a lower resolution by using the viewport stretch mode and setting your project's base resolution to something like 1280×720 (or even lower).

rafaelcastrocouto commented 2 years ago

I don't understand what you mean by "WebAssembly and WebGL overhead" ... if the device don't support WebGL, there's certainly a fallback to standard canvas 2d api. And as far as I know WebAssembly should speed things up not slow then down (otherwise they would just use vanilla JS).

Being a little less smooth in mobile is 100% expected, but I really doubt Godot cannot handle a simple 2d scene with a couple tiles in a modern device with decent FPS, since most web game engines can handle it with lots of particles without problems.

The device is running Android v10 - Chrome 98.0.4758.101, it's a samsumg SM-J600GT (a pretty standard model - I can test in other devices and update the info here)

The viewport wat set to 512x512, the web deploy auto adjusts to the browser window size (same behavior as rezising the game window)

Zireael07 commented 2 years ago

@rafaelcastrocouto: Godot games don't fallback to canvas2d because shaders are used (A LOT). WASM is always slower than native apps (what you would get if you exported your game to Android)

Calinou commented 2 years ago

The device is running Android v10 - Chrome 98.0.4758.101, it's a samsumg SM-J600GT (a pretty standard model - I can test in other devices and update the info here)

Can you test a native Android export on the same device? The Samsung Galaxy J6 was already a low-end device by 2018 standards, which means it'll have trouble running modern mobile games in general.

The viewport wat set to 512x512, the web deploy auto adjusts to the browser window size (same behavior as rezising the game window)

When using the 2d stretch mode, the engine will render at native resolution. This can be too much to handle for low-end mobile devices, hence my recommendation to use the viewport stretch mode instead (or set shrink to 2 in the Project Settings).

rafaelcastrocouto commented 2 years ago

it'll have trouble running modern mobile games in general.

It don't, most web engine 2D games run smoothly with lots of units, physics, particles, etc. (*not 3D)

Maybe I could try to make fallbacks for 2D games... btw I would love to create a "2d pixelart mode" that would set all configuration to optimal settings and allow export UI to html elements (and make use of all native acessibility input stuff) and use canvas2d API to get some real fast web builds.

It makes me sad to see something kind simple being, as you said, "overheaded" in such an amazing engine.

Zireael07 commented 2 years ago

Out of curiosity, what "web engine 2D games" are you comparing to? If you're comparing to Pixi or some other web first engine, then obviously it will perform better on web than Godot, which is a multi-platform engine, and therefore can't super optimize things for web.

rafaelcastrocouto commented 2 years ago

I could make a list but it actually doesn't matter, I'm not comparing how good the performance is.

If any of you checked out the posted rep you would see that there's nothing besides 2 tile nodes with a few 8x8 pixel art tiles. NOTHING ELSE. No physycs, no lightining, no shadows, no pathfinding, no particles, no units, NOTHING!

I'm not believing you are really considering normal for your engine web deploy system (probably the most important for godot because indie games duh) to export a "lighter than flappy bird game" that's unplayable in standard mobile device.

Anyway, I once again reafirm my intention to help with this and create a lighter export system. You can continue under the illusion that everything is fine, but it will not improve your program.

Zireael07 commented 2 years ago

Your device is not a "standard" mobile device. It's four years old, and furthermore, it has a Mali GPU. Mali GPUs are infamous for having really bad OpenGL drivers.

Your device also has a native resolution of 720 x 1480 pixels. If you're really rendering 2 tiles, you don't really need all that resolution and mobiles are very quickly fill rate limited (the more pixels on your screen, the more the performance tanks). The other thing mobiles really don't like is overdraw - if your tiles overlap because they're isometric, the former gets even worse. (Both of those things are called out in the performance documentation)

One thing that I think Godot could do is have some mobile presets to avoid common pitfalls like using the 2d stretch mode, by defaulting to viewport for mobiles just like it defaults to vertex lighting.

rafaelcastrocouto commented 2 years ago

Your device is not a "standard" mobile device. It's four years old, and furthermore, it has a Mali GPU. Mali GPUs are infamous for having really bad OpenGL drivers.

You must be right, I can play freaking Guenshi Impact on the device but a web game with overlapping tiles ... hey that's too much 🙄

If there's no intent of the godot team in implementing a fast 2d web exporter, it's ok... you can just close this. Hope you all have a great time!

Calinou commented 2 years ago

@rafaelcastrocouto As I said above, can you try exporting your project for Android and running it on your device? This can be done to see if the HTML5 export is actually the problem here.

Also, which iOS device did you test?

rafaelcastrocouto commented 2 years ago

I already provided that info ... this is getting tiresome, you guys are clearly aware that you have a problem with your web export system. But instead of talking about ways of fixing it, you are circling around the device capabilities and web vs native... none of those debates will solve your game-engine poor performance on mobile browers.

My only hope with this issue at this point is for future game devs searching "is godot good for web mobile games" to find this and jump out asap.

Zireael07 commented 2 years ago

@rafaelcastrocouto: You provided a Web export, not an Android export. It's possible that you're running into your device limitations and web export is not the problem here, just that Godot is not the right tool for this device. That's why Calinou has asked repeatedly for an Android export to compare.

gianmichelemariani commented 2 years ago

I have to say I tend to agree here. It was mentioned other times by developers that unfortunately the shaders used in Godot are a bit too heavy for mobile html5, even with GLES2. Hopefully the situation will get better with 4 since GLES3 is getting much more attention to deploy on lower end devices.

Also, would you mind testing this and see what kind of performance your device gets? It's webassembly from a non web-native engine:

https://github.com/Dragosha/slasher-prototype

rafaelcastrocouto commented 2 years ago

It runs completely fine for a web game (awesome project btw) ... as expected it's not a super smooth experience as with native apps, but it's playable and feels good. Believe me it's not the device ... I've already tried the same simple build on better machines and I would not make this fuss for no reason.

I'm sorry if I sound a bit agressive, but it's really sad to see this kind of attitude from developers in general. I am from a 3rd world country, but I'm lucky to have access to better stuff. That said, this is not the case for everyone at all. Instead of helping out and offering to test out, some of you acted as if everyone in the world gets a new smartphone from their dads every christmas and that made me feel kinda emotional. Most games developed in godot will end up being played by 3rd world kids in their old parents phones.

Anywayt, I really hope we can work out at least some improvements for 2d games on the web platform and thnks for eveyone listening to my rants ✌

clayjohn commented 2 years ago

Just to add an outside perspective here:

  1. The problem here is not the device, a 4 year old is not problematic. We added GLES2 so that 10+ year old devices could still run Godot games.

  2. There is a huge difference between running a game on the web and running a game on the device. When running a game on the web browser, you don't have direct access to the GPU and everything gets filtered through many layers of API calls. Additionally, web browsers disable many optimizations that are implemented in the engine and in the graphics API's driver. The result is much worse performance.

  3. The key question for us is: "is this an Android performance problem, or is this a web browser performance problem." If it is a problem when exported to Android directly, then it is clearly an engine problem and we need to figure out what is going wrong. If the performance is only an issue when exporting for the mobile web browser, then it may be an engine issue, but may an unavoidable issue with web performance. To know the difference, we need to see the same game exported to android and exported to a mobile web browser so we can start to narrow down what is going on.

Calinou commented 2 years ago

For reference, I tested the web export on a OnePlus 6 (a not so recent flagship phone) and I get a locked 60 FPS. I can't test higher framerates due to V-Sync being forced by Android.

Remember that in the Android landscape, the difference between old and new flagship devices isn't that large in terms of raw CPU/GPU performance. However, the difference between flagships and low-end devices remains huge today – likely even larger than it used to be. This is one of the reasons it's typically better to get an old flagship device instead of a recent low-end device. Unfortunately, the device you have falls in the worst of both worlds; it's an old and low-end device.

I'd try lowering the rendering resolution as I mentioned above and see if it improves performance. Other than that, I don't see much that could be done to improve performance in such simple GLES2 projects.

A few years ago, I remember seeing an effort to create a web-native "Godot scene file interpreter" of sorts which could display Godot scenes (with scripting done in JavaScript). It was promising, but it was very limited and not particularly easy to use. I don't have a link to it right now, but I don't think it's still maintained and working with Godot 3.4.x anyway.

XDRiVE888 commented 2 years ago

Maybe at some point the problem is related to https://github.com/godotengine/godot/issues/58447 becaurse there is low fps too. I have now found a workaround for this problem by using a custom html5 page. In it, I made a patch to rewrite the preserveDrawingBuffer variable to false in the webgl context. @rafaelcastrocouto if you are interested, you can test it on your device. To do this, place unzip this custom html page full-size.zip in your project, and in the html5 export settings in the custom html5 shell column, select this modified html5 page. And test the result.

rafaelcastrocouto commented 2 years ago

Thanks for helping @XDRiVE888 I tryed your file (and replaced the $GODOT_PROJECT_NAME, $GODOT_HEAD_INCLUDE , $GODOT_URL and $GODOT_CONFIG with the project content)

Unfortunetly it did not improve the frame rate (not on desktop neither on the mobile devices I'm testing) I even lowered the resolution to the point it was so pixelated I couldn't read any text and the FPS was still below 20 per second.

Since it makes no sense to keep asking me to test possible solutions, I will propose a test enviroment that will be available to all developers and can be intergrated on your code tests.

@Zireael07 @Calinou You should try testing web exports with chrome devtools CPU throtling and check if the FPS is acceptable. Here's some tutorials on how to use this feature

https://developer.chrome.com/blog/new-in-devtools-61/#throttling https://deanhume.com/cpu-throttling-using-chrome-developer-tools/

Calinou commented 2 years ago

OS: Fedora 34 Browser: Chromium 96 CPU: i7-6700K GPU: NVIDIA GeForce GTX 1080 Monitor: 2560×1440 (144 Hz, hence the game reaching 144 FPS with no throttling)

No throttling Mid-tier mobile Low-end mobile
2022-03-16_18 20 24 2022-03-16_18 22 36 2022-03-16_18 30 23

Since FPS doesn't decrease at all with the mid-tier mobile preset (4× CPU slowdown), this hints at the GPU being a possible bottleneck on your mobile device. With the low-end mobile preset (6× CPU slowdown), FPS starts to drop, but it remains at a much higher level than reported on your device.

Note for those wishing to test this on their own PC: You don't need to reload the page to apply CPU throttling changes – it applies instantly after you change the preset.

rafaelcastrocouto commented 2 years ago

Are you disabling the browser GPU hardware acceleration @Calinou ?

Calinou commented 2 years ago

Are you disabling the browser GPU hardware acceleration @Calinou ?

No, but Chromium on Linux has only had partial GPU hardware acceleration for a long time (chrome://gpu):

image

Disabling WebGL will prevent the project from running, and it's expected that software WebGL implementations are too slow to be playable (even on a very fast CPU).

XDRiVE888 commented 2 years ago

@rafaelcastrocouto as I knew you dont need to replace $GODOT_PROJECT_NAME, $GODOT_HEAD_INCLUDE , $GODOT_URL and $GODOT_CONFIG in a custom html page, becaurce its replaced on export by engine.

rafaelcastrocouto commented 2 years ago

thanks for the info @XDRiVE888, I wasn't aware about it. I was closing the editor and running a simple static server just to be sure that there wasn't anything else messing things up.

@Calinou does it even make sense to throttle the CPU while you have a GTX1080 running?

Calinou commented 2 years ago

does it even make sense to throttle the CPU while you have a GTX1080 running?

Yes, as the CPU can become a bottleneck rather quickly when it's throttled significantly.

rafaelcastrocouto commented 2 years ago

@Calinou do you understand that the purpose is to emulate an old device? have u ever seen an old phone with a freaking GTX1080 attached to it?

Calinou commented 2 years ago

@Calinou do you understand that the purpose is to emulate an old device? have u ever seen an old phone with a freaking GTX1080 attached to it?

Chromium doesn't appear to have GPU throttling capabilities, so this is all I can do on my end.

rafaelcastrocouto commented 2 years ago

@Calinou You don't need GPU throttling because the mobile devices we are trying to emulate here don't have them.

Here's some help on how to turn off GPU in google chrome

SysError99 commented 2 years ago

Running any of unoptimised WebAssembly games (both Godot and Unity) will always have performance issues no matter what platform you are running on due to very high WA + JS bridge overhead. Unless Godot team address the issue and invest on a new pure-JS engine (which runs great or even better than WA on any browsers nowadays), or there will be some kind of new web standards that allow WA to control web elements directly without the bridge, nothing will improve the situation.

Zireael07 commented 2 years ago

Pure JS engines only run better than WASM as long as you stay on the "hot path", which is very easy to fall off from and which differs from browser to browser.

SysError99 commented 2 years ago

Game logic does not need to always be altered already. Even if it goes out of prediction the side effect is pretty much negligible. Still, yes, JS code only runs faster than WASM in some cases/environments. Actually, I should say "WASM-based game engines" instead of just "WASM" in general.

LittleToky commented 7 months ago

Hi everyone! Seems I have same issue. Please help! My 2d game suffers low fps (about 25) when using web export and I open my app on android devices. No matter GLES2 or GLES3 build I use. I do not use any shaders at all (are shaders used inside engine? There are several Light2D nodes in scene in each moment with normal mapped sprites in my game if it matters). I get about 60 fps in both ios and android builds but it's not even possible to play through web. It runs on 60 fps in chrome on my m1 mac book air but I don't think it indicates something. First I've tried to make builds with not optimised code and things like too large images. I've got about 40-50 fps in ios build and about 30-40 fps in android. Cleaning and optimisation resulted in significant performance improvement in ios and android builds but web build stayed as it was about 25 fps.

I tried html template mentioned here, but unfortunately I get an error "Cannot read properties of undefined (reading 'getParameter')"

I tried to build author's project and I see: 60 fps in android build and unstable fps from 27 to 56, mostly about 30 in web version tested on phone. On tablet web fps is rarely higher than 30.

Also I tried Dragosha on both android tablet and android phone - if fps decrease is here it isn't significant. Is there anything else I can try?

My devices: phone OnePlus Nord N200 5G, Android 12, Chrome 120, Quacomm Snapdragon Octa-core tablet HUAWEI MatePad SE, Harmony OS, HUAWEI browser 14.0.5.301, Quacomm Snapdragon 680

Godot v3.5.2.stable.official [170ba337a]

SysError99 commented 7 months ago

@LittleToky Noting that this repository isn't for asking for technical support help, but since I work directly in this field, I may help you figuring out basic things related to the issue.

Yes, anything on the screen needs shaders in order to render it, but you may talk about premade shaders.

The large size of the image shouldn't matter too much as long as it's not unreasonably large, not too many of them, and it stays as a power of 2 if you compress it for the GPU. I made a lot of games with very large size images and it doesn't have issues including on Snapdragon 430 which runs at around 28 FPS.

Godot's GDScript on WASM can't afford a lot of computing power power because GDScript is poorly optimised and on the web it suffered a lot. If you have a lot of game nodes with GDScript attached, you'll immediately see the issue. I mostly wrote Godot web games trying to utilise as little _process block as possible and tried utilising all native methods in it. For example, input handling should directly go to _input block, or directly connect signal to native methods if the method without coding is possible. Async code is also very good at hiding performance issues and making the game feel smooth.

Godot physics doesn't work so well on the web either. If you have many of them, it suffers heavily. You should avoid it if possible.

It's worth mentioning that regardless of anything, OpenGL ES 2.0 (GLES2) should always be preferred because Godot with GLES 3.1 (GLES3) support is rather subpar and performs poor performance on the web platform. Not to mention it also has a significant amount of bugs compared to GLES 2.0. However, many lightmap features may not work correctly in GLES2 and GPU particles will not work in GLES2 mode. I used to have my personal project running GLES3 in HTML5 and it runs poorly. After a quick switch to GLES2 it immediately bumps up to twice the amount of FPS. Noting that the project also uses C# which is also notorious for having poor performance on the web.

LittleToky commented 7 months ago

Thank you for your answer @SysError99 ! 1) Just reported having the same issue with info about more devices 2) As I said, GLES3 -> GLES2 didn't change the situation. I use particles quite a lot (textures - small circle gradients with transparent edges) To say truth it seems that GLES3 build woks better on web on my android phone, but also too slow to say for sure. 3) Physics process I use for counting logic is heavy but I see 25 fps even when it turned off. Nodes quantity isn't dramatic. From Godot "physics" features I use collision shapes - circles and collision polys and move_and_collide for up to 10-15 bodies each frame. Nothing cruel, is it? 4) I'll check everything you suggested to check. Thank you.

After all I'm sure that problem has a place and agree with @rafaelcastrocouto. May be new developers should be informed better about possible troubles with web export. I understand general reason of such situation (WASM) and may be not much can be done here, but I'd like to have this info before. Any case I like Godot very much and I am grateful to all of you

rafaelcastrocouto commented 6 months ago

I'll leave this here in order to point towards improvements to the wasm export process.

"... So the solution was to break everything up into WebAssembly modules, and optionally dynamically linked libraries on native targets."

https://legendofworlds.com/blog/2

vyakhorev commented 6 months ago

In my case very poor performance with Godot 4.3.dev3 WebGL on iOS 16.2 iPhone X was due to directional light - it works like charm on a moderate PC with no dedicated GPU (in Chrome browser) and fails with 1 FPS at Chrome browser on mobile (iPhone XIII as well). Wierd thing is that all meshes on my scene are imported as "cast no shadow" and I tried turning off shadows on the directional light. I even turned off almost all objects on the scene (a few of them were dynamic).

Steps I done to solve my case:

  1. Deleted the directional light.
  2. Set up scene with "sky" ambient light to light up the objects (created environment as a resource, selected it in a camera an in the envornment node, switched background mode to Sky, background color to white and energy multiplier to 1.5, set sky material with some noise, set environment ambient light to white - just some simple actions to light up the scene without an explicit light source).

By far so far works ok on iPhone (both Chrome and Safari).