Multithreading 多线程X11应用程序与OpenGL

Multithreading 多线程X11应用程序与OpenGL,multithreading,opengl,thread-safety,x11,Multithreading,Opengl,Thread Safety,X11,我正在尝试使用libx11创建一个多线程opengl应用程序,每个窗口有一个单独的线程,还有一个管理器线程 我在manager线程中有一个事件循环: while(true) while(XQLength(mPlatformData->display)){ XNextEvent(mPlatformData->display, &event); std::cout << "event" << std::endl; } } whil

我正在尝试使用libx11创建一个多线程opengl应用程序,每个窗口有一个单独的线程,还有一个管理器线程

我在manager线程中有一个事件循环:

while(true)
  while(XQLength(mPlatformData->display)){
    XNextEvent(mPlatformData->display, &event);
    std::cout << "event" << std::endl;
  }
}
while(true)
而(XQLength(mPlatformData->display)){
XNextEvent(mPlatformData->显示和事件);

std::cout众所周知,Xlib有几个在并发访问情况下表现出来的不可修复的运行时问题。我猜您正遇到其中一个问题

这是Xcb最初创建的原因之一:修复Xlib的问题。GLX是针对Xlib指定的,因此对于OpenGL来说,这似乎是一个阻碍。但是Xcb有一个Xlib包装,可以安全地使用它与GLX接口,并且在程序的其余部分仍然使用Xcb:

我认为有两种可能的解决办法:

  • XNextEvent
    周围放置一个
    XLockDisplay
    /Mutex,GLX会调用每个函数;对于普通OpenGL,您不必锁定,只需锁定前缀为
    GLX…
    的函数即可

  • 使用Xcb获得正确的运行时行为,并遵循上面链接的指南,使其与OpenGL/GLX一起工作


  • 你在渲染线程中做什么?在任何情况下,如果你在不同线程之间共享一个Display*连接,你必须调用XInitThreads


    我在每个线程一个显示连接方面有很好的经验。使用XSelectInput获取主线程上的事件。窗口ID可以在不同的显示*连接之间共享。

    正如eile所说,您应该检查是否使用XInitThreads

    当我使用背景线程来绘制动画的窗口时,我能够从中得到一些好的结果。如果你坚持绘制代码,似乎没有什么真正的问题

    如果您需要更多,并且因为您使用的是低级libX11,那么最好只打开多个X11连接,并在每个顶级窗口中使用一个连接。我在10年前开发BeOS跨平台工具包时就这样做了,当时一切都处于比现在更糟糕的状态


    您甚至可以将其用于顶级的事件处理和子窗口。但这需要一些非常棘手的XEvent掩码代码。

    我猜X11和OpenGL是线程不安全的。如果使用一个上下文/线程,GL是线程安全的。根据X11文档,如果调用XInitThreads()应该是安全的首先,我要做的。代表OP发言:OP了解XInitThreads,请参阅他对问题的评论。打开额外的
    Display*
    连接是解决这个问题的一种方法。不幸的是,它消耗了一种罕见的资源:连接。X11服务器目前的形式不太支持很少数量的连接(客户端)一次(256到1024之间);因此,如果每个进程的线程都打开了自己的显示连接,那么连接槽很快就会用完。而且多个显示连接不能共享GLXContexts,或者只是我不能让它们工作。@Dutow:只有当所涉及的上下文是间接呈现上下文时,才能在不同的连接之间共享GLXContexts,即。直接=假呼叫我们在均衡器分布(eqAsync)中有一个示例这将在第二个线程中为每个GPU打开一个显示连接,并为每个GPU打开一个额外的共享上下文以上载GL纹理。好吧,这是在使用glX-因此我的问题是,您在第二个线程中要做什么。代码如下:我使用XInitThreads,这还不够。我不能使用多个显示连接,因为我不能共享GLXContex我实现了第一个解决方案作为快速修复,但我希望有更好的解决方案,我将尝试第二个。