godot icon indicating copy to clipboard operation
godot copied to clipboard

HTML5 export for Godot 4.0.beta10 takes 1-2 minutes to load on macOS

Open Luzzotica opened this issue 2 years ago • 43 comments


Bugsquad note: This issue has been confirmed several times already. No need to confirm it further. Bugsquad note2: Also, please avoid asking when this will be fixed. The issue is confirmed to be with the version of ANGLE used by Chromium, so we are all waiting for Google to ship the fix.


Godot version

4.0.beta10

System information

MacOS Monterey 12.2.1

Issue description

Godot games block the main thread (And potentially crashes it) on MacOS.

Untested for Windows or Linux.

This happens from both a generic build and when you run the project in a browser from the engine.

Steps to reproduce

Create a new project for Godot Beta 10.

Add a UI Button to the screen.

Have it print things out, whatever you wish.

Add an HTML5 export, install the HTML5 export library if necessary.

Click the run on HTML5 button on the top right.

Proceed to wait for 1-2 minutes before the game will fully load.

Minimal reproduction project

TestGodot4Web.zip

Luzzotica avatar Dec 29 '22 01:12 Luzzotica

Duplicate of https://github.com/godotengine/godot/issues/41118 and/or https://github.com/godotengine/godot/issues/68647 (same cause – large size causes slow initialization times).

Calinou avatar Dec 29 '22 16:12 Calinou

@Calinou I feel like this isn't the same as those. I don't believe it's a size issue.

Running locally on MacOS on both Brave and Chrome: Took about ~2 minutes and 30 seconds for the game to load. Both Brave and Chrome wanted to kill the tab. It had locked up the entire browser for (Couldn't go to any other tab).

Running this on Windows, and the game loads in ~10 seconds.

If this is a size issue, then MacOS Chrome and Brave are just INSANELY slow to load things. Which doesn't seem right. Also, since I'm running it locally, I assume the web assembly can load faster... This might be untrue, but I doubt that it is.

Luzzotica avatar Dec 29 '22 17:12 Luzzotica

In that case, it might be shader loading and/or conversion (correct me if I'm wrong, but MacOS converts stuff to ANGLE behind the scenes, doesn't it?)

Zireael07 avatar Dec 29 '22 18:12 Zireael07

In that case, it might be shader loading and/or conversion (correct me if I'm wrong, but MacOS converts stuff to ANGLE behind the scenes, doesn't it?)

I also think may be a shader compilation issue. Chrome definitely uses ANGLE, but I am not sure about Brave. macOS doesn't use ANGLE when running on desktop though.

While attempting to fix the gl_compatibility renderer on macOS I experimented with using ANGLE, but found that the shader compilation times ended up increasing by over 100X. In https://github.com/godotengine/godot/pull/70065 I was able to speed up shader compilation times and get gl_compatibility working on macOS without ANGLE. However, since chrome uses ANGLE, my guess is we are hitting those pathological shader compilation issues anyway. I am not sure what exactly in the shader is causing the issue (it may even be a bug in ANGLE).

clayjohn avatar Jan 02 '23 19:01 clayjohn

Related https://github.com/godotengine/godot/issues/65696

bergice avatar Jan 10 '23 05:01 bergice

The issue of Chrome crashing on MacOS 13 does indeed exist, and Firefox takes over 2 minutes to load.

thomasbergersen avatar Feb 12 '23 15:02 thomasbergersen

I'm completely new to C++ dev, but I would like to help with this issue. What can I do to help?

shinspiegel avatar Feb 20 '23 09:02 shinspiegel

Can confirm, 4.0 RC2 is still taking minutes to load on Brave on MacOS.. Causes my entire browser to lock down completely.

Luzzotica avatar Feb 21 '23 05:02 Luzzotica

The issue still persists in rc4, rc5, rc6. In Forward+, Mobile, and Compability mode. Chrome hangs, Firefox takes a while but loads, and Safari has a infinitely loading spinner and reports the following in the console:

[Error] Unhandled Promise Rejection: CompileError: WebAssembly.Module doesn't parse at byte 1155: can't get 1th argument Type
	promiseEmptyOnRejected
	promiseReactionJob
> Selected Element
< <html lang="en">…</html>
[Error] still waiting on run dependencies:
	onPrintError (tmp_js_export.js:14008)
	(anonymous function) (tmp_js_export.js:737)
[Error] dependency: wasm-instantiate
	onPrintError (tmp_js_export.js:14008)
	(anonymous function) (tmp_js_export.js:739)
[Error] (end of list)
	onPrintError (tmp_js_export.js:14008)
	(anonymous function) (tmp_js_export.js:742)

dhnm avatar Feb 27 '23 15:02 dhnm

In the latest version of Godot Engine 4 (RC 6), the game still completely freeze internet browsers (tested on Chrome and Firefox and MacOS 13.2.1). Will a stable version of Godot really be released today with such a bug?

michaldev avatar Feb 28 '23 23:02 michaldev

Just to confirm - this issue does occur on Godot 4.0 stable, viewing the web export in Chrome 110 on macOS 13.2 on a MacBook Pro 2023 M2. A project containing only a very simple 2D pixel art scene takes 70s to load initially. Is it possible to find a workaround until this is fixed, e.g. strip shaders from the web export?

max-vogler avatar Mar 02 '23 22:03 max-vogler

Is it possible to find a workaround until this is fixed, e.g. strip shaders from the web export?

No, other than staying on Godot 3.x.

(PS: Modern OpenGL/WebGL rendering always uses shaders, no matter how much your custom build is stripped. This is also the case in Godot 3.x.)

Calinou avatar Mar 02 '23 23:03 Calinou

I extracted the shaders from godot 4.0 from the sample linked above and filed a bug. Only 19 shaders are compiled at startup but for some reason (didn't look into why) several shaders, 5 shaders take ~15 seconds each for a total of 1 minute at 15 seconds (on an M1 mac)

https://bugs.chromium.org/p/angleproject/issues/detail?id=8068

greggman avatar Mar 06 '23 19:03 greggman

If you're curious I wrote this code

// extract-shader.js
(function() {
  const programs = [];

  function dumpPrograms(label) {
    if (programs.length) {
      if (label) {
        console.log('//', label);
      }
      console.log(JSON.stringify(programs));
      programs.length = 0;
    }
  }

  globalThis.dumpPrograms = dumpPrograms;

  for (const RenderingContext of [WebGL2RenderingContext, WebGLRenderingContext]) {
    RenderingContext.prototype.linkProgram = function(origFn) {
      return function(prg) {
        console.log('// link', programs.length);
        const shaders = this.getAttachedShaders(prg);
        programs.push(shaders.map(sh => {
          return {
            type: this.getShaderParameter(sh, this.SHADER_TYPE),
            src: this.getShaderSource(sh),
          };
        }));
        origFn.call(this, prg);
      };
    }(RenderingContext.prototype.linkProgram);

    for (const name of ['clear', 'drawArray', 'drawElements', 'drawArraysInstanced', 'drawElementsInstanced']) {
      RenderingContext.prototype[name] = function(origFn) {
        return function(...args) {
          dumpPrograms();
          origFn.call(this, ...args);
        };
      }(RenderingContext.prototype[name]);
    }
  }
})();

And then I added <script src="extract-shaders.js'></script> to the top of the html file and I added importScripts('extrac-shaders.js') to the worker (as I wasn't sure which one uses WebGL, the main thread, the worker, or both). I also added a call to dumpShaders in the onmessage code in the worker and in the onPrint function in the main thread JavaScript since the sample above does so little that I wasn't sure WebGL is actually being called.

In any case, you can use code like this to extract shaders and then code like the one in the chromium bug report to make a minimal repo.

greggman avatar Mar 06 '23 19:03 greggman

So looking into this more, it appears to be an issue with ANGLE running on top of the MacOS OpenGL drivers. Chrome is working to switch over to ANGLE running on top of Metal. You can test that path with

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --use-cmd-decoder=passthrough --use-angle=metal --user-data-dir=<some-random-folder>

In which case the shaders compile faster. Hopefully that will ship soon.

You can verify which backend ANGLE is running on by going to about:gpu

ANGLE running on OpenGL:

GL_RENDERER: ANGLE (Apple, Apple M1 Max, OpenGL 4.1 Metal - 83)

ANGLE running on Metal:

GL_RENDERER: ANGLE (Apple, ANGLE Metal Renderer: Apple M1 Max, Version 13.2.1 (Build 22D68))

Yes, it's confusing that both strings say 'metal' 😅

greggman avatar Mar 06 '23 20:03 greggman

This is fantastic @greggman -- can confirm the project now loads in seconds instead of minutes.

ANGLE (Apple, ANGLE Metal Renderer: Apple M2 Pro, Version 13.2 (Build 22D49))

max-vogler avatar Mar 06 '23 20:03 max-vogler

So we just gotta wait for chrome/safari/brave to migrate to the new Metal Renderer? Because there's no way I'm gonna get my players to run their browser with that special command haha!

Luzzotica avatar Mar 07 '23 15:03 Luzzotica

So we just gotta wait for chrome/safari/brave to migrate to the new Metal Renderer?

correct...

Or you can try to adjust the shaders so they don't provoke the issue in the Apple OpenGL drivers, or pray Apple updates their OpenGL drivers.

If you want to update the shaders in the short term, lowering MAX_LIGHTS lowers the compile time. The issue is probably the way Apple's OpenGL driver handles UBOs. Their might be other work arounds, I'm not sure.

greggman avatar Mar 07 '23 18:03 greggman

Is it possible to fallback to the way Godot 3.x handled web exports while we wait for browsers to migrate to Metal?

evwilliams avatar Mar 16 '23 16:03 evwilliams

If you want to update the shaders in the short term, lowering MAX_LIGHTS lowers the compile time. The issue is probably the way Apple's OpenGL driver handles UBOs. Their might be other work arounds, I'm not sure.

Which value did you test for MAX_LIGHTS, and how much did it speed loading? Looks like it's hardcoded in these 2 places (if you're referring to 2D rendering):

https://github.com/godotengine/godot/blob/1e0f7a12f7c762ee1d73795485b0d00db3cf2ac8/drivers/gles3/rasterizer_canvas_gles3.h#L248

https://github.com/godotengine/godot/blob/1e0f7a12f7c762ee1d73795485b0d00db3cf2ac8/drivers/gles3/rasterizer_canvas_gles3.h#L100

Is there a way we could expose a project setting, then add a web override to decrease it by default in HTML5 exports? This could cause 2D lights to visually break after exporting to HTML5 (depending on the number of lights present in the scene), but it's better than having very long load times.

Is it possible to fallback to the way Godot 3.x handled web exports while we wait for browsers to migrate to Metal?

No, as 3.x featured entirely different and incompatible rendering backends (most notably a GLES2 backend, which is much simpler and more limited).

Given this isn't the only shortcoming of the HTML5 export in 4.x, it may be worth looking into creating a 4to3 project converter. This way, you can downgrade a Godot 4 project to Godot 3 until the HTML5 export matures (and then use 3to4 to convert it back once that happens). This could take a long time to be fixed upstream after all.

Calinou avatar Mar 17 '23 00:03 Calinou

Probably a worse case of this https://github.com/godotengine/godot/issues/56670 (3.x 3D web)

tavurth avatar Mar 17 '23 20:03 tavurth

Hi I just wanted to share my frustration with the bug reported on https://github.com/godotengine/godot/issues/72584. In 3.x exporting to Web was a safe way to ensure your game was playable on many platforms.

Web exports for a very minimal 2D game are unable to be played in chrome on a MAC, however interestingly enough Safari seems to work. It's very unfortunate because web exports being cross platform was a huge selling point for me.

I look forward to progress on this.

chasem-dev avatar Apr 17 '23 15:04 chasem-dev

@Xwaffle1 Please don't bump issues without contributing significant new information. Use the :+1: reaction button on the first post instead.

(Remember that commenting creates a notification for everyone watching the repository. If you want to subscribe to an issue without commenting, click the Subscribe button in the sidebar.)

There's also the workaround described here which you can try by modifying some values in the engine source code, then compiling a custom HTML5 export template: https://github.com/godotengine/godot/issues/70691#issuecomment-1472914415 Testing this workaround and making sure it works will help this issue be resolved faster.

Calinou avatar Apr 17 '23 15:04 Calinou

This looks fixed on the latest macOS Ventura (13.3.1) using Safari (16.4). I'm running this on a 2021 M1 Macbook Pro. I tested a variety of scenes both with Godot 4.0.2 and Godot 3.5.2 with the WebGL2 export. Safari uses Metal and not ANGLE for WebGL2 and perhaps that's why the behaviour is different.

The only error I get in the console is [Error] USER WARNING: Project setting: rendering/limits/global_shader_variables/buffer_size exceeds maximum uniform buffer size of: 16384 which is mitigated by changing the project setting to the recommended value.

Firefox still hangs for a bit before loading the scene. Running a CPU Profile reveals that most of the work is stalling on some sort of shader introspection from a GL library. Which means that Firefox is running on a GL layer.

SCR-20230421-ucoh

The recommended Chrome workaround (https://github.com/godotengine/godot/issues/70691#issuecomment-1456888280) works for me.

In general there is quite a bit of variability, but given the majority of people are probably using Chrome this is still dependent on them switching to the Metal backend.

pbantolas avatar Apr 21 '23 22:04 pbantolas

With 4.1 in RC state, is this receiving any love? Safari seems to do the right thing so one can always point at that, but this may still catch people out by surprise.

Morpheu5 avatar Jun 28 '23 13:06 Morpheu5

Won't get any focus until after 4.1 is released, only high impact bugs and crashes get much focus at that stage, unless this is a trivial fix and someone finds it pretty much immediately

AThousandShips avatar Jun 28 '23 13:06 AThousandShips

I guess I meant if this was somehow lost in the changelog that I missed but yeah, thanks for the update anyway :)

Morpheu5 avatar Jun 28 '23 13:06 Morpheu5

If the issue is open it hasn't been fixed :) no PR has been linked to this so no fix seems to be in progress right now, keep looking here for updates like that

AThousandShips avatar Jun 28 '23 13:06 AThousandShips

If the issue is open it hasn't been fixed :) no PR has been linked to this so no fix seems to be in progress right now, keep looking here for updates like that

I guess the confusion comes from the fact that issues such as this leave a strong indication that it would be worked on for 4.1. While that is now clearly not the case, perhaps a better indication of a timeline for investigation/fix could be added to the documentation, just so people embarking on potential new projects can plan accordingly?

mgc8 avatar Jun 28 '23 17:06 mgc8

How does an issue on a separate repository indicate anything about the priorities in this one? This issue is clearly marked "4.x", and no PR has been opened for this so no solution is clear.

perhaps a better indication of a timeline for investigation/fix could be added to the documentation

We don't track these things in the documentation, that's what the issues here are for

AThousandShips avatar Jun 28 '23 17:06 AThousandShips