godotengine / godot

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

[WebGL2] A simple scene takes 45 seconds to load #21957

Closed ikelaiah closed 4 years ago

ikelaiah commented 6 years ago

Godot version: 3.0.6 64-bit

OS/device including version: Windows 10 64-bit HP Folio 9480m, i5 4th gen, 8GB RAM, HD4400. Firefox - 62.

Issue description: A simple scene containing a low poly Mars with 2k color texture; it takes 45 seconds to load. 2018-09-11 08_33_03-mars demo basic

Steps to reproduce:

  1. Download and open my project file
  2. Export as HTML
  3. Execute the main HTML file
  4. Wait... takes about 45 seconds to load.

Minimal reproduction project: I attached the project file here. mars-basic.zip

ghost commented 6 years ago

Can confirm, took about 45 seconds here as well, very odd that it's so exact.

ikelaiah commented 6 years ago

I did another test by opening the project in Godot 3.1 alpha, exported to HTML5, and I waited for 45 seconds as well before I see the planet. Perhaps I've done something amiss.

Calinou commented 6 years ago

Does it load faster if you create a WorldEnvironment and set an empty Environment (with no sky)? Perhaps the slowness is caused by panorama generation.

Also, try replacing the planet texture with a single color to see if it's related to texture loading.

ikelaiah commented 6 years ago

A WorldEnvironment and set an empty Environment (with no sky - solid colour) loads in 2 seconds. A WorldEnvironment and set an empty Environment (with no sky - solid colour) with the planet using spatial material coloured white, loads in 45 seconds. A WorldEnvironment and set an empty Environment (with no sky - solid colour) with the planet without using spatial material, loads in 45 seconds.

ikelaiah commented 6 years ago

A WorldEnvironment and set an empty Environment (with no sky - solid colour) with a spherical mesh instance without using spatial material, loads in 45-50 seconds.

Zireael07 commented 6 years ago

So the mesh accounts for ~40 seconds of those 45? What happens if you place a different mesh, e.g. a simple cube?

ikelaiah commented 6 years ago

Removed the new SphereMesh and replaced it with a new CubeMesh (no spatial material). ~45 secs.

muiroc commented 6 years ago

Last month I was invenstigating webgl performance and I'm pretty sure it is libangle taking forever to link some shaders

with firefox try typing "about:config" in the url bar then search for "webgl.disable-angle" and set it to true, then reload the page

of course its not a solution, it's only to check if it is the same issue

edit: attached the test (non godot) project, maybe it could be useful, (tested only firefox) opening index.html should take a long time to load, (there will be some debug info in the console) you can edit main.js to load your own shaders godot_shaders_webgl_perf.zip

to obtain the shader source i used a custom build, the text was printed to the console when it took too much to compile/link, if you do the same be aware when copying the text that similar lines gets collapsed into one (for example multiple endifs directives)

ikelaiah commented 6 years ago

@muiroc Wow! I did exactly as you said, the loading time is only 3s.

However, I'm getting WebGL context lost everytime I scale the browser window.

muiroc commented 6 years ago

I see, in my case (3.1) fullscreen works with firefox 62, but hdr rendering is not working, Chrome loses context before finishing loading (weird since both uses angle? dunno)

Are you getting some interesting errors in the console? in chrome i had some max varying vectors and framebuffer incomplete error messages in the console before the context loss

the equivalent of "webgl.disable-angle" in Chrome is to create a shortcut and add the --use-gl=desktop command line option

another factor in laptops is if the browser is using the integrated or dedicated video card (optimus)...

btw I didn't investigate further because I've got an ANCIENT geforce 635m with old drivers so i didn't really expect much from it (even if it works in desktop gl)

instead i was waiting to see what happens with the gles2 backend (im using very light 3d, and can get away with vertex lighting (which even in 3.1 compiles kind of fast on angle and crappy hardware like mine (apart frome the default material which is a complex spatial and still takes 45 secs so it would be nice to override... ok enough parentheses)))

Also, while i'm using firefox, considering the browsers marketshare, chrome should be the reference target

ikelaiah commented 6 years ago

Initially I was aiming for Chrome, but Chrome lost WebGL context even before the loading was completed. Like you, I also ended up with bunch of errors on Chrome and that's why I ended up with Firefox as it shows something... after 45 seconds.

HD4400 is the only thing I have on this laptop, so yeah, unable to test with a dedicated graphics card.

I agree. Considering the browsers marketshare, Chrome should be the reference target.

leonkrause commented 6 years ago

This has been an issue ever since 3.0 with WebGL 2 on Windows, in fact we have numerous issues describing such long freezes: #16050 #19089 #19093

For 3.1 I hope we can switch the default to WebGL 1, where shader compilation is less of an issue.

Until then you can manually change to WebGL 1 in the project settings, set rendering/quality/driver/driver_name to GLES2 (i.e. WebGL 1). You can use the Override for... button at the top to set this only for web export.

Leaving this open for visibility.

ikelaiah commented 6 years ago

I did a test, same project file using Godot 3 Alpha 1 and exported using GLES2. Nothing come up on browser but I received plenty of errors.

I attached screenshots here. I hope you'll find this useful.

2018-09-17 10_04_39-mars demo 2018-09-17 10_05_04-mars demo 2018-09-17 10_05_25-mars demo 2018-09-17 10_07_44-mars demo

muiroc commented 6 years ago

Just for the record, about GLES3 and Angle, this looks related to #14902 as setting the MAX_LIGHT_DATA_STRUCTS and MAX_REFLECTION_DATA_STRUCTS to, for example 8, allows the shader to link in about 500ms, and works also in Chrome

this is an export of the original repro case (with 397b01d) mars-basic_exp_web_mod.zip

for now this only modifies the shader text (in index.js, check _glShaderSource at line 10474)

NOTE if in the console there are two numbers and an assertion please reload, dunno what that is, happens since I updated emsdk, even in other non godot projects (with assertions says something about FS iirc)

Another note: in my case, starting Chrome with the "--use-gl=desktop" option actually would start it in software rendering mode! You can check this and other interesting info typing "chrome://gpu" in the address bar

ikelaiah commented 6 years ago

Confirming @muiroc findings.

The modified build loads. Initially two numbers and an assertion came up in the console. After reloaded, the Mars appeared in 4 seconds. 45s to 4s? That's a great improvement from end-users point of view.

Thanks.

Gliderz commented 5 years ago

Hello, I have the same issue here:

-A scene with 5 meshs, 3 materials, 5 textures files and 1 environnement map. -Export as HTML -takes about 45 seconds to load. -I make a tons of test with 1/2 mesh, with/without material, with/without textures files, with/without environnement map.. -try in Godot 3.0.6 and Godot 3.1 alpha -always 45 seconds to load. (no errors in debug mode)

I'm looking for the issue in google and i find this topic. I think it's the same shader loading problem. I have dowload the mars-basic.zip and the mars-basic_exp_web_mod.zip for try to understand the issue (and the Muiroc'fix), but I'm not sure to understand the part with godot_shaders_webgl_perf.zip. I try to load the html in my web browser but nothing appear...

@Muiroc ,Can you tell me more about how you obtain the shader source and how to edit main.js to load your own shaders, please?

Thanks

muiroc commented 5 years ago

@Gliderz sure,

When Godot loads a shader, it needs to call glShaderSource: that function is defined in "index.js".

If you open it, you will see that its not very readable, since it is stripped of all unnecessary spaces (uglified) so first you need to reformat it (beautify/prettyprint): for example I'm using Visual Studio Code with the Beautify extension, so just open "index.js" then run a command with ctrl+shift+p, type Beautify, enter!

Now you can search for the "_glShaderSource" function (the identifiers are prefixed with an underscore), which will look like this: (NOTE: don't mistake it with "emscripten_glShaderSource", those are functions returned by getProcAddress)

function _glShaderSource(shader, count, string, length) {
    *stuff*
}

The "shader" parameter is the glsl source code (so, not the godot shading language!). Before passing it to GLctx (which is the WebGL Context) we can do some interesting things to it, like replacing some values!

function _glShaderSource(shader, count, string, length) {
    var source = GL.getSource(shader, count, string, length);
    source = source.replace(/(#define MAX_LIGHT_DATA_STRUCTS )(\d+)/, "$18")
    source = source.replace(/(#define MAX_REFLECTION_DATA_STRUCTS )(\d+)/, "$18")
    GLctx.shaderSource(GL.shaders[shader], source)
);

(If you need help with regexes (like I do lol) there are some cool online tools)

This is ( if iirc! ) the change used in "mars-basic_exp_web_mod" to speed up the loading, it is just replacing the number on the right of MAX_LIGHT_DATA_STRUCTS and MAX_REFLECTION_DATA_STRUCTS with an "8"

That's it, save, reload page (if using chrome hold the reload button and select the bottom option to fully reload)

WARNING: this is just an HACK that most likely WILL NOT WORK reliably!!!

Lastly to get the text, at first i printed to the console, but it is a MESS and annoying to copy paste, so in the end I just created a hidden DIV and setted its innerhtml to the shader source, but i currently cant find the code snippet!

To identify the original shader, in the godot shader just add an uniform with a name easy to search like "uniform float SHADERNAME_the_actual_shader_name;

To avoid repeating this for every export, as long as you using the same godot build/version, you can even set the index.js file as read-only, (it always gets copied as-is), or just reexport only the pck file

In general the slowdown is caused (for some shaders) by the angle library, which is used by default in Firefox and Chrome on Windows (so, a lot of users...)

godot_shaders_webgl_perf shows nothing on screen, it was just a playground to test shader modification more easily, the output is in the console

Now, I don't know what 3D features are you using, but if it is "kinda low end" it should be better to wait for GLES2 (WebGL1) bugfixing and see what happens, if i understand it correctly there are plans to remove the GLES3 (WebGL2) backend for the web build

ikelaiah commented 5 years ago

Tested with Godot 3.1 Beta 6, using GLES2. Exported to HTML5 with no issues. The scene loads in 3-4 seconds (using FireFox 65.0.2).

Tested with Godot 3.1 Beta 10, Beta 11, RC1 and Official 3.1 using GLES2. Exported to HTML5 with no issues. The scene loads in 3-4 seconds (using FireFox 65.0.2).

ikelaiah commented 5 years ago

It seems the issue has been resolved in Godot 3.1. We can close this I suppose.

Many thanks to all who helped.

akien-mga commented 5 years ago

The issue is still valid for GLES3 / WebGL 2 I think. But indeed, using GLES2 / WebGL 1 is the safer option for people planning to make web games.

LordOdin commented 5 years ago

Im having some insane load times on a basic scene with a cube and a few 3D sprites with the same texture

jknightdoeswork commented 5 years ago

This should help https://github.com/godotengine/godot/pull/30898

clayjohn commented 4 years ago

We are no longer working on the WebGL2 backend due to poor driver support on most systems. We recommend you use the GLES2/WebGL backend instead.

Unfortunately, that means this bug just isn't going to be fixed in GLES3/WebGL2, sorry.

gnat commented 4 years ago

Correct me if I'm wrong, but won't drivers eventually catch up? Or is there some other backend beyond GLES3/WebGL2?

I don't feel like gaming on the web is going away anytime soon.

clayjohn commented 4 years ago

They may. However we are abandoning our GLES3 backend in favour of Vulkan for 4.0. Version 3.2 is the last one to support the GLES3 backend.

Pretty much all hardware still supports WebGL1 significantly better than WebGL2. We were spending too much development effort creating hacks to appease WebGL2 when WebGL1 just works better and is faster anyway.

nathanfranke commented 3 years ago

This won't be fixed in GLES3/WebGL2, but what about GLES2/WebGL1? This bug is most definitely still reproducible in GLES2. See my Flappy Bird Demo: https://flappy.nathan.gq/ \ I clocked it at 59 seconds from page load to actual gameplay. It takes less than a second to load on desktop. The performance on web is okay, but seems to be only around 30 fps compared to 4000 fps desktop.

Edit: Note that this 59 second delay only seems to be on first page load, or when cache is disabled.

Calinou commented 3 years ago

Edit: Note that this 59 second delay only seems to be on first page load, or when cache is disabled.

Which browser are you using? Chromium-based browsers often have better WebGL performance than Firefox, especially on Linux.

clayjohn commented 3 years ago

@nathanfranke it loads instantly on my phone. Using chrome for android.

Calinou commented 3 years ago

It also loads instantly here in Firefox 83 on Linux. It runs at 144 FPS if the window is kept at a small size (this is a general, non-Godot-specific issue with WebGL in Firefox on Linux).

nathanfranke commented 3 years ago

Very peculiar. On both firefox android and chrome android it takes unreasonably long for me. On PC I had differing load times but at one point it was still this slow on chrome desktop.

nathanfranke commented 3 years ago

Here is an example of the bug occurring on Google Chrome 86. System info: Manjaro 20.2, GTX 960, NVidia drivers 450xx

https://youtu.be/o6dfgP4LGrQ

clayjohn commented 3 years ago

@nathanfranke the video shows that the issue is with scene loading not with shader compiling. Shaders aren't compiled until the first frame.

You may want to open a new issue to focus on your particular problem.

Calinou commented 2 years ago

To anyone stumbling upon this: can you try building the latest 3.x branch from source (which includes https://github.com/godotengine/godot/pull/53411) and see if the issue persists? You'll need to compile both an editor and HTML5 export template. Set the shader caching mode to Asynchronous + Cache in the Project Settings, then export the project to HTML5.

tavurth commented 2 years ago

This is confirmed in 3.x (current stable @ 3.4.2 also)

https://github.com/tavurth/godot-simple-fps-camera

Pretty much all hardware still supports WebGL1 significantly better than WebGL2. We were spending too much development effort creating hacks to appease WebGL2 when WebGL1 just works better and is faster anyway.

This makes sense, but GLES3 works fine for 2D projects, this only affects 3D projects.

OptimistPro commented 2 years ago

Hello. I'm using godot 3.4.1 gles2. An empty project takes 45 seconds to load in html5. What could be the problem?

Calinou commented 2 years ago

Hello. I'm using godot 3.4.1 gles2. An empty project takes 45 seconds to load in html5. What could be the problem?

This is an unrelated issue. Please open a separate issue with a minimal reproduction project attached.