OpenGL在辅助线程中渲染

rja*_*cks 26 opengl multithreading sdl

我正在编写一个3D模型查看器应用程序作为业余爱好项目,也作为一个测试平台来尝试不同的渲染技术.我正在使用SDL来处理窗口管理和事件,以及用于3D渲染的OpenGL.我的程序的第一次迭代是单线程的,运行得很好.但是,我注意到单线程程序导致系统变得非常缓慢/滞后.我的解决方案是将所有呈现代码移动到不同的线程中,从而释放主线程来处理事件并防止应用程序无响应.

该解决方案间歇性地工作,程序经常因为主要来自X窗口系统的变化(并且在我看来奇怪)一组错误而崩溃.这让我质疑我最初的假设,即只要我的所有OpenGL调用都发生在创建上下文的线程中,一切都应该仍然有效.在花了一天的大部分时间在互联网上寻找答案后,我彻底难过了.

更简洁:是否可以在主线程以外的线程中使用OpenGL执行3D渲染?我是否仍可以使用此配置的跨平台窗口库(如SDL或GLFW)?有没有更好的方法来做我想做的事情?

到目前为止,我一直在使用C++在Linux(Ubuntu 11.04)上进行开发,尽管如果有一种在这些语言中效果更好的解决方案,我也对Java和Python感到满意.

更新:根据要求,一些澄清:

  • 当我说"系统变得迟钝"时,我的意思是与桌面交互(拖动窗口,与面板交互等)变得比正常情况慢得多.移动我的应用程序的窗口需要几秒钟的时间,而其他交互只是慢到足以令人讨厌.
  • 至于干扰合成窗口管理器...我正在使用Ubuntu 11.04附带的GNOME shell(现在远离Unity ...)我找不到任何禁用桌面效果的选项,例如以前的发行版.我认为这意味着我没有使用合成窗口管理器......虽然我可能是非常错误的.
  • 我认为"X错误"是由于我在终端上收到的错误消息导致的服务器错误.更多细节如下.

我的应用程序的多线程版本出现的错误:

XIO:X服务器上的致命IO错误11(资源暂时不可用)在73个请求(73个已知处理)之后":0.0",剩余0个事件.

X请求失败的错误:BadColor(无效的Colormap参数)失败请求的主要操作码:79(X_FreeColormap)失败请求中的资源ID:0x4600001失败请求的序列号:72输出流中的当前序列号:73

游戏:../../ src/xcb_io.c:140:dequeue_pending_request:断言`req == dpy-> xcb-> pending_requests'失败.中止

我总是得到上面三个错误中的一个,我得到的一个变化,显然是随机的,这(我的眼睛)似乎证实我的问题确实源于我使用线程.请记住,我正在学习,因此我很有可能在我的无知中,我有一些相当愚蠢的东西.

解决方案:对于遇到类似问题的任何人,我通过将调用移至SDL_Init(SDL_INIT_VIDEO)渲染线程并使用互斥锁锁定上下文初始化来解决我的问题.这可以确保在将要使用它的线程中创建上下文,并且它可以防止主循环在初始化任务完成之前启动.启动过程的简化概述:

1)主线程初始化struct将在两个线程之间共享,并包含互斥锁.
2)主线程生成渲染线程并暂停一段时间(1-5ms),使渲染线程有时间锁定互斥锁.暂停后,主线程在尝试锁定互斥锁时阻塞.
3)渲染线程锁互斥,初始化SDL的视频子系统并创建OpenGL上下文.
4)渲染线程解锁互斥锁并进入其"渲染循环".
5)主线程不再被阻塞,因此在完成初始化步骤之前锁定和解锁互斥锁.

请务必阅读答案和评论,那里有很多有用的信息.

dat*_*olf 7

只要一次只触摸一个线程的OpenGL上下文,就不应该遇到任何问题.你说甚至你的单线程程序使你的系统运行缓慢.这是指整个系统还是仅适用于您自己的应用程序?在单线程OpenGL程序中应该发生的最糟糕的情况是,处理该一个程序的用户输入变得滞后,但系统的其余部分不受影响.

如果你使用一些合成窗口管理器(Compiz,KDE4 kwin),请试试如果你禁用所有合成效果会发生什么.

当您说X错误时,您是指客户端错误,还是X服务器日志中报告的错误?后一种情况不应该发生,因为X服务器必须能够处理任何类型的格式错误的X命令流,并且最多会发出警告.如果它(X服务器)崩溃,这是一个错误,应该报告给X.org.

如果您的程序崩溃,那么它与X的交互就会出现问题; 在这种情况下,请向我们提供其变体中的错误输出.