Why do I get "unsupported shader version" using "#version 300 es" at emscripten?

2.7k Views Asked by At

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?

2

There are 2 best solutions below

0
On BEST ANSWER

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

SDL_CreateWindowAndRenderer(CANVAS_WIDTH, CANVAS_HEIGHT, SDL_WINDOW_OPENGL, &window, &renderer);
1
On

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.