1

I don't know why I get a "unsupported shader version" error message using #version 300 es in my vertex shader with the latest emscripten 1.39. With #version 100 it works fine.

const GLchar* vertex_shader_code[] = {
      "#version 300 es\n"
      "precision mediump float; \n"

      "void main() { \n"
           "gl_Position = vec4(0.0, 0.0, 0.0, 1.0); \n"
      "} \n"
};
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);

SDL_version compiled;
SDL_version linked;

SDL_VERSION(&compiled);
SDL_GetVersion(&linked);
printf("Compiled SDL version: %d.%d.%d\n", compiled.major, compiled.minor, compiled.patch);
printf("Linked SDL version: %d.%d.%d\n", linked.major, linked.minor, linked.patch);

SDL_Init(SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer(CANVAS_WIDTH, CANVAS_HEIGHT, 0, &window, &renderer);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);

GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, vertex_shader_code, 0);
glCompileShader(vertex_shader);

auto compile_success = 0;
auto compile_info_lenght = 0;
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &compile_success);

if(compile_success == GL_FALSE) {
   glGetShaderiv(vertex_shader, GL_INFO_LOG_LENGTH, &compile_info_lenght);
   std::string vertex_shader_log(compile_info_lenght, ' ');

   glGetShaderInfoLog(vertex_shader, compile_info_lenght, NULL, &vertex_shader_log[0]);
   int n = vertex_shader_log.length();
   char char_array[n + 1];
   strcpy(char_array, vertex_shader_log.c_str());
   printf("%s\n", char_array);

   glDeleteShader(vertex_shader);
   return 0;
}

For the built I use emcc -s main.cpp -o index.html --shell-file shell.html -s USE_SDL=2 -s FULL_ES3=1

Message:

Compiled SDL version: 2.0.9
Linked SDL version: 2.0.9
ERROR: unsupported shader version

What I'm doing wrong?

PowerNow
  • 363
  • 1
  • 2
  • 15
  • 1
    Why are you calling `SDL_GL_SetAttribute()` before `SDL_Init()`? – genpfault May 12 '20 at 15:59
  • Hi @genpfault, I tried it now directly after SDL_Init() but unfortunately same error. – PowerNow May 12 '20 at 16:42
  • Also, why are you anywhere near the SDL_Renderer stuff if you're going to use OpenGL ES? You can't (officially) inter-operate between the two, there's no way to query SDL_Renderer for the GL state it may or may not clobber. – genpfault May 12 '20 at 16:49
  • Any change if you also specify [`-s MAX_WEBGL_VERSION=2`](https://emscripten.org/docs/porting/multimedia_and_graphics/OpenGL-support.html#webgl-friendly-subset-of-opengl-es-2-0-3-0)? – genpfault May 12 '20 at 16:53
  • 1
    Might also need `SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES)` to force SDL down a more EGL-y/GLES-y code path. *Might*. Depends on how much violence the Emscripten ports folks are doing to SDL this particular week :) – genpfault May 12 '20 at 16:55
  • I tried ```-s MIN_WEBGL_VERSION=2 -s MAX_WEBGL_VERSION=2``` and ```SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES``` but same error. – PowerNow May 13 '20 at 09:14
  • The reason why I use SDL/openGL is that I want to render the GUI with SDL2 and the 3D-scene with webGL/openGL ES 3.x. – PowerNow May 13 '20 at 09:17

2 Answers2

1

Without your full program, it is difficult to see everything that is wrong. You need to build with the correct options, call your WASM module correctly from JavaScript, and set up everything correctly in SDL and OpenGL.

Here is a working example:

//  main.cpp
#include <stdio.h>
#include <stdarg.h>
#include <emscripten.h>
#include <SDL.h>
#include <SDL_opengles2.h>

SDL_Window *sdlWindow;

static const char *vertexShaderSource[] = {
    "#version 300 es\n"
    "in vec4 position;\n"
    "void main(void) {\n"
    "  gl_Position = vec4(position.xyz, 1.0);\n"
    "}\n"
};

static const char *fragmentShaderSource[] = {
    "#version 300 es\n"
    "precision mediump float;\n"
    "out vec4 fragColor;\n"
    "void main(void) {\n"
    "  fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
    "}\n"
};

static void
fatal(const char *const fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    vprintf(fmt, args);
    printf("\n");
    va_end(args);
    for (;;) {
        SDL_Delay(1000);
    }
}

static GLuint
compileShader(GLenum shaderType, const char **shaderSource)
{
    GLuint shdr = glCreateShader(shaderType);
    glShaderSource(shdr, 1, shaderSource, nullptr);
    glCompileShader(shdr);
    GLint isCompiled = 0;
    glGetShaderiv(shdr, GL_COMPILE_STATUS, &isCompiled);
    if (isCompiled == GL_FALSE) {
        GLint maxLength = 0;
        glGetShaderiv(shdr, GL_INFO_LOG_LENGTH, &maxLength);
        char *errorString = (char *) malloc(maxLength + 1);
        glGetShaderInfoLog(shdr, maxLength, &maxLength, errorString);
        fatal("Compile failed: %s", errorString);
    }
    return shdr;
}

static void
_set_SDL_Attribute(SDL_GLattr attr, int value, const char *attrName)
#define set_SDL_Attribute(x, v) _set_SDL_Attribute(x, v, #x)
{
    if (SDL_GL_SetAttribute(attr, value) != 0) {
        fatal("SDL set attrib failed: %s, %s", attrName, SDL_GetError());
    }
}

static void
setupSDL(void)
{
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        fatal("Unable to init SDL: %s", SDL_GetError());
    }
    SDL_version compiled;
    SDL_version linked;
    SDL_VERSION(&compiled);
    SDL_GetVersion(&linked);
    printf("Compiled SDL version: %d.%d.%d\n",
           compiled.major, compiled.minor, compiled.patch);
    printf("Linked SDL version: %d.%d.%d\n",
           linked.major, linked.minor, linked.patch);
    set_SDL_Attribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
    set_SDL_Attribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    set_SDL_Attribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
    set_SDL_Attribute(SDL_GL_DOUBLEBUFFER, 1);
    set_SDL_Attribute(SDL_GL_DEPTH_SIZE, 24);
    SDL_Renderer *renderer;
    if (SDL_CreateWindowAndRenderer(400, 400, SDL_WINDOW_OPENGL,
                                    &sdlWindow, &renderer) < 0) {
        fatal("Unable to create windown: %s", SDL_GetError());
    }
    SDL_GLContext glContext = SDL_GL_CreateContext(sdlWindow);
    if (glContext == NULL) {
        fatal("Unable to create context: %s", SDL_GetError());
    }
    printf("GL Version={%s}\n", glGetString(GL_VERSION));
    printf("GLSL Version={%s}\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
}

static void
setupOpenGL(void)
{
    GLuint shaderProgram = glCreateProgram();
    GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource);
    GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER,
                                          fragmentShaderSource);
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glUseProgram(shaderProgram);
    static const GLfloat vertices[] = { 0.0f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f };
    GLuint vbo;
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof (vertices), vertices,
                 GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);       // Input offset is zero.
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);       // Black
}

static void
mainLoop(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    SDL_GL_SwapWindow(sdlWindow);
}

int
main(void)
{
    setupSDL();
    setupOpenGL();
    emscripten_set_main_loop(mainLoop, 0, true);
    return 0;
}

Compile with these options:

emcc main.cpp -O3 -Wall -Wextra -Werror -s WASM=1 -s USE_SDL=2 -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -o foo.js

Launch from HTML like this:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <h1>Wasm Test Page</h1>
    <canvas id=canvas width=400 height=400 oncontextmenu="event.preventDefault()"></canvas>
    <script>var Module = { canvas: document.getElementById('canvas') }; </script>
    <script src="foo.js"></script>
</body>
</html>

If everything works, you should see a red triangle on a black background in your browser window.

HTH.

Robert Bruce
  • 681
  • 1
  • 5
  • 10
  • 1
    Had to put this to `setupSdl` function to get it to work. Sorry for single line comment. SO does not support multiline code snippets. `GLint max_vertex_attribs; glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs); for (GLint i = 0; i < max_vertex_attribs; i++) { glDisableVertexAttribArray(i); }` – Rokannon Sep 05 '22 at 12:39
0

For those with the same problem, the solution is SDL_WINDOW_OPENGL.

SDL_CreateWindowAndRenderer(CANVAS_WIDTH, CANVAS_HEIGHT, SDL_WINDOW_OPENGL, &window, &renderer);
PowerNow
  • 363
  • 1
  • 2
  • 15