Search code examples
c++openglsdlglew

Access violation when using glDebugMessageCallback() with SDL?


It seems that I cant use glDebugMessageCallback function, the throws an Access violation error on the very next line of code.

ERROR: Exception thrown at 0x0000000000000000 in DEBUG.exe:
0xC0000005: Access violation executing location 0x0000000000000000.

ErrorHandler.hpp

#define GLCall(x) x;\
    if(isError) __debugbreak();

static bool isError{ false };
namespace ErrorHandler {
    void APIENTRY GLDebugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam);
}

ErrorHandler.cpp

void APIENTRY ErrorHandler::GLDebugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
{
    isError = true;
    const char* _source;
    const char* _type;
    const char* _severity;

    switch (source) ...
    switch (type) ...
    switch (severity) ...

    if (_severity != "NOTIFICATION") {
        fprintf(stderr, "OpenGL error [%d]: %s of %s severity, raised from %s: %s\n",
            id, _type, _severity, _source, message);
    }
 }

Game.cpp

Game::Game(const char* title, uint16_t width, uint16_t height)
{
    if (SDL_Init(SDL_INIT_VIDEO) < 0) ...

    m_window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
    if (!m_window) ...
    
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);

    SDL_GL_SetSwapInterval(1);
    glewExperimental = GL_TRUE;
    if (glewInit() != GLEW_OK) ...
    m_context = SDL_GL_CreateContext(m_window);
    if (!m_context) ...

    printf("%s\n", glGetString(GL_VERSION));

#ifdef _DEBUG
    glEnable(GL_DEBUG_OUTPUT);
    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
    glDebugMessageCallback(ErrorHandler::GLDebugMessageCallback, 0);
#endif
    m_run();
}

I've tried:

  1. Moving the glDebugMessageCallback to diffrent lines (directly after initializing glew, after creating context).

  2. I've tried to use another function as a callback.

  3. I've tried to explicitly set the OpenGL version (4.6.0) and (4.4.0).

  4. I've tried to remove any sdl flags (profile flag and version flags).

Everything gives the same result (Access violation).


Solution

  • You must call

    SDL_GL_MakeCurrent(m_window, m_context);
    

    to activate your OpenGL context prior to calling any OpenGL functions. Otherwise the OpenGL functions do not know which context to operate on. Presumably GLFW did that for you automatically, but SDL does not.

    I'm not familiar with GLEW, but there's a good chance that glewInit also expects a valid context to be active. So the order of operations should be as follows:

    m_window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
    // ...
    m_context = SDL_GL_CreateContext(m_window);
    SDL_GL_MakeCurrent(m_window, m_context);
    
    glewExperimental = GL_TRUE;
    if (!glewInit()) // ...
    
    printf("%s\n", glGetString(GL_VERSION));
    // ...
    glDebugMessageCallback(ErrorHandler::GLDebugMessageCallback, 0);