当我在我的OpenGL游戏中实现过程对象的并行初始化和更新时,我必须创建多个共享对象的OpenGL上下文,并为每个线程绑定一个,以便我可以并行地创建/更新VBO。
我从这篇博客文章中得到了如何做的想法,并且像这样进行了第一次实现(用C++编写,但是这个问题也适用于C语言)。
这段代码在Linux下开发时运行良好,直到我将游戏转移到Windows后出现了问题。 在Intel和AMD的GPU上,它总是在启动时崩溃。在Nvidia上,它大多数时候都可以工作,但是运行几次之后也会在相同的地方崩溃:由其中一个池线程发出的第一个OpenGL调用,它是
最终,我们发现
我从这篇博客文章中得到了如何做的想法,并且像这样进行了第一次实现(用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():不支持所请求的转换操作