在 Linux 上与 GLUT 共享上下文

Posted

技术标签:

【中文标题】在 Linux 上与 GLUT 共享上下文【英文标题】:shared context with GLUT on Linux 【发布时间】:2015-07-18 03:16:51 【问题描述】:

在我当前的设置中,我有两个显示器由两个 GPU 驱动。使用 GLUT,我为每个窗口创建了两个窗口(每个显示器一个),并通过在绘图调用中调用 glutSetWindow() 从主线程渲染每个窗口。

绘制调用将 Texture2D 渲染为球体(使用 gluSphere()),但 Texture2D 每隔几秒就会换成另一个图像。我已经设置了一个包含 2 个 Texture2D 的数组,因此我可以在显示当前 Texture2D 的同时加载下一个图像。只要一切都在主线程中运行,这就会很好。

问题是调用 glTexImage2D() 来加载下一个图像,挂起我的绘图调用,所以我需要在不同的线程上调用 glTexImage2D()。在不同的线程上调用 glTexImage2D() 会崩溃,因为 OpenGL 上下文似乎没有共享。 GLUT 似乎没有提供共享上下文的方法,但我应该能够通过 glXGetCurrentContext() 在 Linux 上获取上下文。

我的问题是,如果我通过此调用获取上下文,我怎样才能使其成为共享上下文?这甚至可以与 GLUT 一起使用吗?另一种选择是切换到不同的库来替换 GLUT,比如 GLFW,但在这种情况下,我会失去一些方便的函数,比如 gluSphere()。如果上下文不能与 GLUT 共享,有什么建议吗?

【问题讨论】:

【参考方案1】:

对于 GLX,上下文共享是在上下文创建时建立的;与 WGL 不同,您不能将这种共享作为事后的想法。由于 GLUT 没有上下文共享功能(FreeGLUT 可能有,但我不确定),这并不简单。

我有两个显示器,由两个 GPU 驱动。

除非这些 GPU 是 SLi-ed 或 CrossFire-ed,否则您无法在它们之间建立上下文共享。

问题是调用 glTexImage2D() 来加载下一个图像,挂起我的绘图调用,所以我需要在不同的线程上调用 glTexImage2D()。

如果图片大小相同,使用 glTexSubImage2D 替换。还可以使用像素缓冲区对象异步加载图像数据,使用甚至不需要 OpenGL 上下文的辅助线程!

概述步骤:

在 OpenGL 上下文线程中:

发起转移

glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboID) void *p = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); 信号传输线程 继续正常的绘图操作

在转移线程中

开始传输的信号

将数据复制到映射缓冲区 信号 OpenGL 上下文线程

在 OpenGL 上下文线程中:

完成传输的信号

glUnmapBuffer glTex[Sub]Image sync = glFenceSync 继续使用纹理进行绘制

关于绘图循环的进一步迭代

使用超时时间 0 轮询 syncglClientWaitSync 如果等待同步返回信号切换到新纹理并删除旧纹理 否则继续使用旧纹理绘制

【讨论】:

感谢 datenwolf,这太棒了!我切换到 glTexSubImage2D() ,它似乎已经是一个小的改进。我正在尝试为异步数据加载编写所有代码。您能否推荐在传输线程完成时如何向 OpenGL 上下文线程发出信号?您知道以 0 毫秒超时调用 glutTimerFunc() 是否是一个安全的解决方案?或者同步布尔值是否应该在绘制调用中检查传输线程是否已完成?谢谢! @Jary316:通常的方法是condition variables,它是从 GLUT 空闲函数轮询的。使用 CV 的好处是,轮询线程在等待变量时进入睡眠状态(如果超时为 0,另一个线程将获得调度,这可能会释放 CV)。当然,对于延迟要求很高的情况,对原子访问的布尔值进行简单的自旋锁定也可以。 非常感谢!我快要上班了!它略微褪色,但不是完全褪色,但我的意思是只需要调整一些参数!我必须在 glBindBuffer() 之后但在 glMapBuffer() 之前调用 glBufferData() (如果有错请告诉我)。 @Jary316:这个想法是在初始化时创建一个大型 PBO(glGenBuffers、glBindBuffer、glBufferData)并(重新)将其用作所有进一步传输的暂存区(仅 glMapBuffer glUnmapBuffer)– .原则上你可以做很多funny tricks using buffer orphaning。一般来说,您希望最大限度地减少对 glBufferData 和 glTexImage 的调用量(总是尝试使用“…Sub…”变体来做事)。 快速提问:为什么需要 glClientWaitSync / glFenceSync?这两个调用都发生在上下文线程中,所以我想我也许可以在那里交换纹理。你怎么看?

以上是关于在 Linux 上与 GLUT 共享上下文的主要内容,如果未能解决你的问题,请参考以下文章

在 Linux 上的上下文之间共享 OpenGL 对象

Windows 上 Eclipse 中的 OpenGL 和 GLUT

GLUT 叠加层有啥用?

在终端应用程序中使用 opengl(没有 glut/glew)[关闭]

glut 库中缺少 glutInitContextVersion()

macOS (c++) 上支持 hidpi 视网膜的 GLUT 问题