Skip to content

SDL2 fails to create opengl window in wasm64 builds #20273

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

Open
jspanchu opened this issue Sep 16, 2023 · 2 comments
Open

SDL2 fails to create opengl window in wasm64 builds #20273

jspanchu opened this issue Sep 16, 2023 · 2 comments

Comments

@jspanchu
Copy link
Contributor

jspanchu commented Sep 16, 2023

SDL2 fails to create an opengl window with error message "Could not create GLES window surface"

Reproducible code:

#include "SDL.h"
#include <emscripten.h>
#include <webgl/webgl2.h>

#include <stdio.h>
#include <string.h>

#define WIDTH 640
#define HEIGHT 480

void onDraw(void *arg) {
  SDL_Window *window = *((SDL_Window **)arg);
  glClear(GL_COLOR_BUFFER_BIT);
  glDrawArrays(GL_TRIANGLES, 0, 3);
  SDL_GL_SwapWindow(window);
}

int main(int argc, char *argv[]) {
  int res = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
  if (res) {
    fprintf(stderr, "Error initializing SDL %s", SDL_GetError());
  }
  SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);

  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);

  SDL_Window *window = SDL_CreateWindow("OpenGL Window", SDL_WINDOWPOS_CENTERED,
                                        SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT,
                                        SDL_WINDOW_OPENGL);
  if (!window) {
    fprintf(stderr, "Couldn't create window: %s\n", SDL_GetError());
    return 0;
  }
  SDL_SetWindowResizable(window, SDL_TRUE);

  SDL_GLContext context = SDL_GL_CreateContext(window);
  if (!context) {
    fprintf(stderr, "Couldn't create context: %s\n", SDL_GetError());
    return 0;
  }

  GLuint vertex_shader;
  GLuint fragment_shader;
  GLuint program;
  {
    const GLchar *source = "attribute vec4 apos;"
                           "attribute vec4 acolor;"
                           "varying vec4 color;"
                           "void main() {"
                           "color = acolor;"
                           "gl_Position = apos;"
                           "}";
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex_shader, 1, &source, NULL);
    glCompileShader(vertex_shader);
  }
  {
    const GLchar *source = "precision lowp float;"
                           "varying vec4 color;"
                           "void main() {"
                           "gl_FragColor = color;"
                           "}";
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment_shader, 1, &source, NULL);
    glCompileShader(fragment_shader);
  }
  program = glCreateProgram();
  glAttachShader(program, vertex_shader);
  glAttachShader(program, fragment_shader);
  glLinkProgram(program);
  glUseProgram(program);
  // clang-format off
  const float pos_and_color[] = {
    //     x,     y, r, g, b
       -0.6f, -0.6f, 1, 0, 0,
        0.6f, -0.6f, 0, 1, 0,
        0.f,   0.6f, 0, 0, 1,
    };
  // clang-format on
  GLuint vbo;
  glGenBuffers(1, &vbo);
  glBindBuffer(GL_ARRAY_BUFFER, vbo);
  glBufferData(GL_ARRAY_BUFFER, sizeof(pos_and_color), pos_and_color,
               GL_STATIC_DRAW);
  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 20, 0);
  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 20, (void *)8);
  glEnableVertexAttribArray(0);
  glEnableVertexAttribArray(1);

  emscripten_set_main_loop_arg(onDraw, &window, 0, 1);
}

32-bit works.

$ emcc main.c -o index.html -sUSE_SDL=2 -sUSE_WEBGL2
$ python3 -m http.server 

image

64-bit doesn't work

$ emcc main.c -o index.html -sMEMORY64=1 -sMAXIMUM_MEMORY=6GB -sALLOW_MEMORY_GROWTH -sWASM_BIGINT=1 -sUSE_SDL=2 -sUSE_WEBGL2
$ python3 -m http.server 

image

Version of emscripten/emsdk:

emcc --version
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.46-git (7c7321c265c47d54dacdd25d00c2c3c9ec2a8425)
Copyright (C) 2014 the Emscripten authors (see AUTHORS.txt)
This is free and open source software under the MIT license.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Version of browser:
Chromium Version 119.0.6011.0 (Developer Build) custom (64-bit)

@sbc100
Copy link
Collaborator

sbc100 commented Sep 18, 2023

Thats interesting, I thought that SDL2 itself currently fails to compile with wasm64. I currently see:

/usr/local/google/home/sbc/dev/wasm/emscripten/cache/ports/sdl2/SDL-release-2.24.2/src/SDL_assert.c:263:25: error: cast to 'char *' from smaller integer type 'int' [-Werror,-Wint-to-pointer-cast]
  263 |             char *buf = (char *) EM_ASM_INT({
      |                         ^~~~~~~~~~~~~~~~~~~~~
  264 |                 var str =
      |                 ~~~~~~~~~
  265 |                     UTF8ToString($0) + '\n\n' +
      |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  266 |                     'Abort/Retry/Ignore/AlwaysIgnore? [ariA] :';
      |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  267 |                 var reply = window.prompt(str, "i");
      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  268 |                 if (reply === null) {
      |                 ~~~~~~~~~~~~~~~~~~~~~
  269 |                     reply = "i";
      |                     ~~~~~~~~~~~~
  270 |                 }
      |                 ~
  271 |                 return allocate(intArrayFromString(reply), 'i8', ALLOC_NORMAL);
      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  272 |             }, message);
      |             ~~~~~~~~~~~
1 error generated.

Did you somehow work around this error? I recently landed this change is that first step in fixing the SDL2 build: #20258

@jspanchu
Copy link
Contributor Author

jspanchu commented Sep 18, 2023

Yep, there's a work around that's not obvious from my other PR #20276. I should've mentioned it there.

  1. In order for SDL2 to build I've had to change my SDL_assert.c to use EM_ASM_PTR instead. And the other change is in SDL_emscriptenmouse.c to use MAIN_THREAD_EM_ASM_PTR.
  2. After that, a01c286 fixed GLES surface creation.

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

No branches or pull requests

2 participants