英文:
Access violation when using glDebugMessageCallback() with SDL?
问题
看起来我不能使用glDebugMessageCallback函数,它在代码的下一行立即抛出了访问冲突错误。
```none
错误:在DEBUG.exe中的地址0x0000000000000000处引发了异常:
0xC0000005:执行位置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();
}
我尝试过:
-
将glDebugMessageCallback移动到不同的行(直接在初始化glew之后,在创建上下文之后)。
-
尝试使用另一个函数作为回调。
-
明确设置OpenGL版本(4.6.0)和(4.4.0)。
-
尝试删除任何SDL标志(配置文件标志和版本标志)。
所有这些都导致相同的结果(访问冲突)。
<details>
<summary>英文:</summary>
It seems that I cant use glDebugMessageCallback function, the throws an Access violation error on the very next line of code.
```none
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:
-
Moving the glDebugMessageCallback to diffrent lines (directly after initializing glew, after creating context).
-
I've tried to use another function as a callback.
-
I've tried to explicitly set the OpenGL version (4.6.0) and (4.4.0).
-
I've tried to remove any sdl flags (profile flag and version flags).
Everything gives the same result (Access violation).
答案1
得分: 2
你必须调用
SDL_GL_MakeCurrent(m_window, m_context);
在调用任何OpenGL函数之前激活你的OpenGL上下文。否则,OpenGL函数不知道要在哪个上下文上操作。可能GLFW会自动为你完成这个步骤,但SDL不会。
我不熟悉GLEW,但很有可能glewInit
也需要一个有效的激活上下文。因此,操作的顺序应该如下:
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);
英文:
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);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论