samdauwe / BabylonCpp

A port of Babylon.js to C++
Apache License 2.0
284 stars 37 forks source link

Wasm experiment / Part 2 #64

Closed pthom closed 4 years ago

pthom commented 4 years ago

Hello Sam,

Here are some additions to this branch. I know I still need to make a complete explanation of the modifs in this branch, but for now I will concentrate on the wasm issues.

Status updates:

Do you have time to take a look at the rendering issues with emscripten? I include below some possible hints.

OpenGL / Glsl versions / OpenGl Loader

There are 4 things to set: they are different between desktop ad emscripten. May be they need to be investigated.

120 fps forced in the browser

I temporailly forced the fps to 120 in emscripten, just to try to see the maximum performance we can obtain.

void RunnerEmscripten::Run()
{
  ...
  //int fps = 0; // 0 <=> let the browser decide. This is the recommended way, see https://emscripten.org/docs/api_reference/emscripten.h.html#browser-execution-environment
  int fps = 120;
  emscripten_set_main_loop_arg(emscripten_imgui_main_loop, NULL, fps, true);
  ...
}

Run with SDL and / or GLFW:

SDL is a new possible backend, even on desktop! See external/CMakeLists_imgui.cmake

option(IMGUI_RUNNER_USE_SDL "Build babylon sdl version" ON)
if (NOT EMSCRIPTEN)
    option(IMGUI_RUNNER_USE_GLFW "Build babylon glfw version" ON)
else()
    set(IMGUI_RUNNER_USE_GLFW OFF)
endif()

Hack for glad and emscripten

See external/glad_wasm_dummy/include/glad/glad.h: with emscripten, glad.h will actually include the opengl headers.

#ifndef __EMSCRIPTEN__
#error "This header is reserved for emscripten"
#endif

#include <GLES3/gl3.h>
#include <GLES3/gl2ext.h>

Problem with emscripten and some OpenGL (deprecated?) functions

For the moment, the emscripten only build because (by chance), the "glfw3.h" headers provides some functions not provided in the gl headers provided by external/glad_wasm_dummy/include/glad/glad.h.

Of course, this include shoud absolutely be removed. I left it as a temporary hack.

See src/BabylonImGui/src/GL/gl_rendering_context.cpp:

// FIXME! Using deprecated Gl Apis?
// There is an issue with emscripten builds: the build only works of glfw is included!
// We have errors like "use of undeclared identifier 'GL_MULTISAMPLE', 'GL_BLEND_SRC', etc."
// For example, it seems like GL_MULTISAMPLE is deprecated
#include <GLFW/glfw3.h>

Cheers!

pthom commented 4 years ago

Demo here: http://traineq.org/BabWasm.mp4

samdauwe commented 4 years ago

Hello Pascal,

Amazing! Really nice work!! Thanks for the updates and the demo video.

The performance looks great and 30% percent of the examples that is working is already good news. I thought that getting the textures loaded would be more difficult but you have this already working.

Post-processes are working in wasm but not in the master branch, that is weird.

I am also seeing that issue with disappearing texture texture on desktop with procedural textures. The first frame is correct and the next frame the texture disappears. Maybe it is related what we see in wasm. Therefore it would be easier to debug this issue first in the desktop version and then check if it resolves the problem for wasm.

I did not look in full detail into all the changes that you made, but maybe we could target also OpenGL ES3.0 on desktop for better consistency with the web version, unless you think that is not necessary?

I have time now to further work on this, I will send you an update tomorrow on my progress.

Cheers, Sam

pthom commented 4 years ago

I did not look in full detail into all the changes that you made, but maybe we could target also OpenGL ES3.0 on desktop for better consistency with the web version, unless you think that is not necessary?

I am not very experienced in OpenGL versions actually. However, I think that targeting the same versions on web and desktop would be a good idea, and would simplify the maintenance.

Are you willing to investigate on this? I am currently working on a different subject (async loading , in order to avoid the monstruous 360MB preload).

For this, the 4 things I mentionned before should probably be modified:

There are 4 things to set: they are different between desktop ad emscripten. May be they need to be investigated.

  • OpenGL Version: see Select_Gl_Version() inside runner_glfw.cpp, runner_sdl.cpp and runner_emscripten.cpp
  • Glsl version: see GlSlVersion() inside these same files
    • OpenGl Loader: see InitGlLoader() inside the same files: we use glad on desktop, and nothing on emscripten
  • Glsl shader versions: see src/BabylonCpp/include/babylon/shaders/shadersinclude/glsl_version_3.h. it also varies between desktop and emscripten

Concerning the glad loader, it was generated using the online generator. I do not remember exactly which options I had chosen, but the content of external/glad/include/glad/glad.h seems to suggest that it would support the following apis gl=4.4, gles2=3.2, gles1=1.0.


Some questions concerning my investigations on the async loading.

My intent is to emulate the javascript async mode, even in C++. For this we need to have a "service" that emulates the background browser process. This service will download files in the background and call the success/error callbacks on completion.

I would prefer not to reinvent this wheel, and introduce possible bugs because it is actually complex. I was thinking of adding a new library, such as xhawk18/promise-cpp, which add javascript-like promises. In order to have a "service", we would need to add also boost.asio, so that we could write code like this

int main() {
    boost::asio::io_service io; // this is the background service
    loadfile(io, filename).then([=] {
       processCallbacks();
    });
    io.run();
    return 0;
}

What do you think of adding such dependencies?


Other remark: In the future, I would suggest also considering adding another dependency, C++ requests that would make loading from urls simple.

samdauwe commented 4 years ago

I did not look in full detail into all the changes that you made, but maybe we could target also OpenGL ES3.0 on desktop for better consistency with the web version, unless you think that is not necessary? I am not very experienced in OpenGL versions actually. However, I think that targeting the same versions on web and desktop would be a good idea, and would simplify the maintenance. Are you willing to investigate on this?

Yes, I also think it will simplify the maintenance and the testing. I am currently working in the branch _v4_renderingissues to test if we can get it working with OpenGL ES 3.0 on desktop.

I am currently working on a different subject (async loading , in order to avoid the monstruous > 360MB >preload).

For this, the 4 things I mentionned before should probably be modified:

There are 4 things to set: they are different between desktop ad emscripten. May be they need to be investigated.

  • OpenGL Version: see Select_Gl_Version() inside runner_glfw.cpp, runner_sdl.cpp and runner_emscripten.cpp
  • Glsl version: see GlSlVersion() inside these same files
  • OpenGl Loader: see InitGlLoader() inside the same files: we use glad on desktop, and nothing on emscripten
  • Glsl shader versions: see src/BabylonCpp/include/babylon/shaders/shadersinclude/glsl_version_3.h. it also varies between desktop and emscripten

Concerning the glad loader, it was generated using the online generator. I do not remember exactly which options I had chosen, but the content of external/glad/include/glad/glad.h seems to suggest that it would support the following apis gl=4.4, gles2=3.2, gles1=1.0.

Thanks for this information, I will try out the online generator.

Some questions concerning my investigations on the async loading.

My intent is to emulate the javascript async mode, even in C++. For this we need to have a "service" that emulates the background browser process. This service will download files in the background and call the success/error callbacks on completion.

I would prefer not to reinvent this wheel, and introduce possible bugs because it is actually complex. I was thinking of adding a new library, such as xhawk18/promise-cpp, which add javascript-like promises. In order to have a "service", we would need to add also boost.asio, so that we could write code like this

int main() {
    boost::asio::io_service io; // this is the background service
    loadfile(io, filename).then([=] {
       processCallbacks();
    });
    io.run();
    return 0;
}

What do you think of adding such dependencies?

Using boost.asio and xhawk18 is fine for me. I did not use this library before but it seems like a standalone module that does not require the full boost library. For now I think we could use any depedency needed and look in the future if we can avoid them.

Related to this, the team working on BabylonJS native implemented their own asynchronous dispatching system (with no external depedencies) that is included in the arcana.cpp repo but it relies on C++ coroutines so we need to update to C++20. An example of using the async dispatching system can be found in this example. But boost asio is more used and therefore better tested.

Other remark: In the future, I would suggest also considering adding another dependency, C++ requests that would make loading from urls simple.

Thanks for the advice.

Cheers, Sam