【发布时间】:2021-02-05 14:57:46
【问题描述】:
当我在我的 OpenGL 游戏中实现程序对象的并行初始化和更新时,我必须使用共享对象创建多个 OpenGL 上下文,并为每个线程绑定一个,这样我就可以并行创建/更新 VBO。
我从this blog post 得到了如何做到这一点的想法,并像这样进行了我的第一个实现(在 C++ 中,但这个问题也与 C 相关):
/* ... */
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
SDL_Window* window = SDL_CreateWindow("Title",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
Options::width, Options::height, video_flags);
// Create one SDL context per thread
std::vector<SDL_GLContext> threads_glcontexts(globalThreadPool.get_num_threads());
for(auto& t_ctx: threads_glcontexts) {
t_ctx = SDL_GL_CreateContext(window);
}
// Main thread context
SDL_GLContext main_glcontext = SDL_GL_CreateContext(window);
// Setup one context per thread
//
// This function only returns when all threads
// in the pool have executed the given function.
globalThreadPool.run_in_every_pool_thread([&](unsigned thread_idx) {
SDL_GL_MakeCurrent(window, threads_glcontexts[thread_idx]); // ← BROKEN CODE
});
/* ... */
这段代码在 Linux 下开发时运行了好几个月,直到我将游戏移植到 Windows。然后事情就出了问题:在 Intel 和 AMD GPU 上,总是在启动时崩溃。在 Nvidia 上,它大部分时间都可以工作,但运行几次后,它也在同一个地方崩溃:其中一个池线程发出的第一个 OpenGL 调用,它是glGenBuffers()。
最终我们发现wglGetCurrentContext() 在有问题的线程上返回了0,这导致我们发现SDL_GL_MakeCurrent() 在某些线程中失败,并出现以下错误:
- wglMakeCurrent():句柄无效
- wglMakeCurrent():不支持请求的转换操作
问题:如何使用 SDL2 在不同线程上正确设置多个具有共享对象的 OpenGL 上下文?
【问题讨论】:
标签: c++ c multithreading opengl sdl-2