Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allows compiling with emscripten #897

Merged
merged 1 commit into from May 27, 2019
Merged

Conversation

tanis2000
Copy link
Contributor

This PR simply allows compiling any project using SDL2 with cargo web. It's just a matter of avoiding linking the SDL2 library as the port from emscripten will be used instead.

@Cobrand
Copy link
Member

Cobrand commented May 27, 2019

Thanks! If you know of additional steps that are unique to sdl2 for emscripten rust, I would be glad to hear them! We definitely need more documentation regarding everything that is not desktop related.

@Cobrand Cobrand merged commit 776c72e into Rust-SDL2:master May 27, 2019
@tanis2000
Copy link
Contributor Author

This should be enough to get SDL2 working with the browser. I guess all the rest is up to the application using SDL2. Anyway I'm trying to port a simple project of mine over to the browser so I'll let you know if I stumble upon any blocks

@tanis2000
Copy link
Contributor Author

@Cobrand I have an almost working prototype here on the webgl branch: https://github.com/tanis2000/minigame-rust/tree/webgl

But I still have an issue as it looks like for some reason I'm getting an invalid SDL2 renderer with the browser:

thread 'main' panicked at 'Invalid renderer', /Users/tanis/Documents/tanis2000-rust-sdl2/src/sdl2/render.rs:912:13

I can't figure out why this is happening though, do you have any clue?

@Cobrand
Copy link
Member

Cobrand commented May 27, 2019

The error comes from the function in engine.rs L90~
On webgl the opengl driver must not be named opengl but something else. I think you can skip this function entirely as it was only useful on Mac/windows to use opengl instead of directx/metal/ect. On the web, the only driver available should be webgl.

@tanis2000
Copy link
Contributor Author

That's not entirely true.
I have a similar application in C that does run in the browser through Emscripten and I'm using OpenGLES 2.0 just like I'm doing with this one:

#if defined(__IPHONEOS__) || defined(__ANDROID__) || defined(__EMSCRIPTEN)
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#endif

I am actually printing the list of OpenGL drivers that SDL2 is returning and I get only opengles2 and software, so there isn't even a choice tbh :)

I tried skipping setting the index but the result is the same. There must be something else going on that I'm overlooking.

@Cobrand
Copy link
Member

Cobrand commented May 27, 2019

This panic must come from some rust code, otherwise it'd be just a segfault. The message "invalid renderer" doesn't look like it's coming from rust code though, so it's probably an SDL message.

Can you enable backtraces and maybe using the SDL documentation we'll be able to see more clearly?

@tanis2000
Copy link
Contributor Author

I've almost got there. I had to skip over the canvas completely and use the gl_create_context() function to get the correct OpenGL driver working.

Now I'm able to clear out the screen ;)

I need to find the equivalent of the canvas.present() call. In my C code I just call SDL_GL_SwapWindow() but I couldn't find a wrapper for that one and maybe there's a better way as this one fails on iOS, where I need to do something like:

  SDL_SysWMinfo info;
  SDL_VERSION(&info.version);
  SDL_GetWindowWMInfo(win->window, &info);

  glBindFramebuffer(GL_FRAMEBUFFER, info.info.uikit.framebuffer);
  glBindRenderbuffer(GL_RENDERBUFFER,info.info.uikit.colorbuffer);

@Cobrand
Copy link
Member

Cobrand commented May 27, 2019

@tanis2000
Copy link
Contributor Author

Yes it looks like it should work. I have to rewrite some code dependent on canvas to actually see if it works again on all the different platforms, though.
I’ll keep you posted

@tanis2000
Copy link
Contributor Author

I moved forward and it's almost working, but I'm getting an allocation error that I'm not having on the desktop and I'm struggling figuring out where the actual problem lies.
I've updated the https://github.com/tanis2000/minigame-rust/tree/webgl branch if you want to have a look at it.

The current error is the following:

Uncaught abort("alignment fault") at Error
    at jsStackTrace (http://localhost:8000/main.js:1667:13)
    at stackTrace (http://localhost:8000/main.js:1684:12)
    at abort (http://localhost:8000/main.js:11888:44)
    at alignfault (http://localhost:8000/main.js:1053:3)
    at SAFE_HEAP_LOAD_i32_4_4 (wasm-function[171210]:39)
    at __ZN4core4cell13Cell_LT_T_GT_3get17ha7292d0f274620b2E (wasm-function[3605]:45)
    at __ZN5alloc2rc8RcBoxPtr6strong17h9d76bc796af30b74E (wasm-function[1084]:51)
    at __ZN5alloc2rc8RcBoxPtr10inc_strong17h974f8b274d2ef40bE (wasm-function[1089]:36)
    at __ZN61__LT_alloc__rc__Rc_LT_T_GT__u20_as_u20_core__clone__Clone_GT_5clone17h42ec3c5edf9a6750E (wasm-function[1102]:36)
    at dynCall_ii (wasm-function[5737]:14)

@Cobrand
Copy link
Member

Cobrand commented May 28, 2019

The problem could come from many places... If you could create a minimal example where this problem happens, we might be able to make some progress. That'll allow you to know whether it's coming from rust code, from the rust <-> C bindngs (bindgen?), from your C SDL2 library, from something else, ...

@tanis2000
Copy link
Contributor Author

tanis2000 commented May 28, 2019

There you go, minimum reproduction of the issue: https://github.com/tanis2000/rust-sdl2-wasm

I didn't even need to go further and complete the drawing stuff as it shows the issue even before that.
It looks like my context is being destroyed while the emscripten main loop is running.

@tanis2000
Copy link
Contributor Author

I don't know if it makes any sense but it looks like those kind of errors happen only when calling out to the sdl2::sys functions that in turn call the C code. Does this ring a bell by any chance?

@tanis2000
Copy link
Contributor Author

I narrowed down this issue further.. it's happening only if you call unsafe code in the loop. As soon as you call some unsafe code, like simple OpenGL calls, it starts corrupting. I wonder why though...

@Cobrand
Copy link
Member

Cobrand commented May 31, 2019

Do you have an example of the call in question that crashes? I suspect that the sizes of the structs/pointers sent to opengl are the wrong size. I suspect the bindgen generation (which is for linux x86_64) is not adapted to webgl somehow.

@tanis2000
Copy link
Contributor Author

tanis2000 commented May 31, 2019

It can be pretty much anything.. just have a look at the current master of https://github.com/tanis2000/rust-sdl2-wasm
Run it with cargo web start and open it in the browser and check the console log. It's full of garbage. The only way to make sure that it runs correctly is to remove all of the GL calls and the SDL2 initialization (which in turn initializes OpenGL so if you're right it messes up with pointers as well).

That kinds of defeats what I said before though because it doesn't matter if I call unsafe code in the main loop.. it's more like that if I call into any unsafe code anywhere in the app it corrupts memory.

But then I'm wondering.. since we're using the SDL2 version that's in the emscripten port, we shouldn't be using the one from this crate, or are we actually linking both for some reason? I have no clue what cargo is doing under the hood when it comes to those things.

@tanis2000
Copy link
Contributor Author

It looks like the closure needs to be saved on the heap to avoid stack-allocated memory to be released and thus leading to undefined behavior and memory corruption. I've updated the sample project with the correct code and it works fine.

I've also updated my own little game project that compiles pretty much anywhere now, so we definitely have a sample project using Rust + SDL2 that compiles to all the desktop and mobile platforms and now to all major browsers as well, hurray! :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants