【问题标题】:shared context with GLUT on Linux在 Linux 上与 GLUT 共享上下文
【发布时间】: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 共享,有什么建议吗?

【问题讨论】:

    标签: linux multithreading opengl textures 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?这两个调用都发生在上下文线程中,所以我想我也许可以在那里交换纹理。你怎么看?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-23
    • 2021-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多