我正在编写一个3D模型查看器应用程序,作为一个业余项目,也作为一个测试平台来尝试不同的渲染技术。我正在使用SDL处理窗口管理和事件,并使用OpenGL进行3D渲染。我的程序的第一次迭代是单线程的,运行得很好。然而,我注意到单线程程序导致系统变得非常缓慢/滞后。我的解决方案是将所有呈现代码移到不同的线程中,从而释放主线程来处理事件,并防止应用程序变得没有响应。
这个解决方案间歇性地工作,由于主要来自X窗口系统的一组不断变化(在我看来很奇怪)的错误,程序经常崩溃。这让我质疑了我最初的假设,即只要我所有的OpenGL调用都发生在创建上下文的线程中,一切都应该正常。在花了一天的大部分时间在互联网上搜索答案后,我彻底被难住了。
更简洁地说:是否可以在主线程之外的线程中使用OpenGL执行3D渲染?在这种配置下,我仍然可以使用跨平台窗口库(如SDL或GLFW)吗?有没有更好的方法来做我想做的事?
到目前为止,我一直在使用C++在Linux(Ubuntu 11.04)上进行开发,尽管如果有更好的解决方案,我对Java和Python也很满意。
更新:根据要求,一些澄清:
- When I say "The system becomes sluggish" I mean interacting with the desktop (dragging windows, interacting with the panel, etc) becomes much slower than normal. Moving my application s window takes time on the order of seconds, and other interactions are just slow enough to be annoying.
- As for interference with a compositing window manager... I am using the GNOME shell that ships with Ubuntu 11.04 (staying away from Unity for now...) and I couldn t find any options to disable desktop effects such as there was in previous distributions. I assume this means I m not using a compositing window manager...although I could be very wrong.
- I believe the "X errors" are server errors due to the error messages I m getting at the terminal. More details below.
我在应用程序的多线程版本中遇到的错误:
XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0.0" after 73 requests (73 known processed) with 0 events remaining.
X Error of failed request: BadColor (invalid Colormap parameter) Major opcode of failed request: 79 (X_FreeColormap) Resource id in failed request: 0x4600001 Serial number of failed request: 72 Current serial number in output stream: 73
Game: ../../src/xcb_io.c:140: dequeue_pending_request: Assertion `req == dpy->xcb->pending_requests failed. Aborted
我总是会出现上面三个错误中的一个,我得到的错误各不相同,显然是随机的,(在我看来)这似乎证实了我的问题实际上源于我对线程的使用。请记住,我是边学习边学习的,所以很有可能在我的无知中,我一路上做了一些相当愚蠢的事情。
解决方案:对于任何有类似问题的人,我通过将对SDL_Init(SDL_Init_VIDEO)
的调用移动到呈现线程并使用互斥锁锁定上下文初始化来解决我的问题。这样可以确保在将要使用它的线程中创建上下文,并防止在初始化任务完成之前启动主循环。启动程序的简化概述:
1) Main thread initializes struct
which will be shared between the two threads, and which contains a mutex.
2) Main thread spawns render thread and sleeps for a brief period (1-5ms), giving the render thread time to lock the mutex. After this pause, the main thread blocks while trying to lock the mutex.
3) Render thread locks mutex, initializes SDL s video subsystem and creates OpenGL context.
4) Render thread unlocks mutex and enters its "render loop".
5) The main thread is no longer blocked, so it locks and unlocks the mutex before finishing its initialization step.
一定要阅读答案和评论,那里有很多有用的信息。