5

我在我的应用程序中使用了两个 OpenGL 上下文。

第一个用于渲染数据,第二个用于后台加载和生成 VBO 和纹理。

当我的加载上下文生成一个 VBO 并将其发送到我的渲染线程时,我会在我的 VBO 中获得无效数据(全为零),除非我调用glFlushglFinish在加载上下文上创建 VBO 之后。

我认为这是由于我的加载上下文没有任何缓冲区交换或任何告诉 GPU 开始处理其命令队列并且什么都不做(这导致渲染上下文侧的 VBO 为空)。

据我所见,这种刷新在 Windows 上不是必需的(使用 Nvidia GPU 测试,即使没有刷新也可以工作),但在 linux/macOS 上是必需的。

苹果文档上的这个页面说调用glFlush是必要的(https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/OpenGLESApplicationDesign/OpenGLESApplicationDesign.html

如果您的应用在多个上下文之间共享 OpenGL ES 对象(例如顶点缓冲区或纹理),您应该调用 glFlush 函数来同步对这些资源的访问。例如,您应该在一个上下文中加载顶点数据后调用 glFlush 函数,以确保其内容已准备好被另一个上下文检索。

但是是调用glFinish还是glFlush必要的,或者是否有更简单/更轻的命令可以实现相同的结果?(哪个是必要的,glFlush或者glFinish?)

此外,在某处是否有关于此的文档或参考资料?我找不到任何提及,并且它似乎在实现之间的工作方式不同。

4

1 回答 1

5

如果您在线程 A 中操作任何对象的内容,则在发生两件事之前,这些内容对其他线程 B 是不可见的:

  1. 修改对象的命令已完成glFlush不完成命令;您必须使用glFinish同步对象来确保命令完成。

    请注意,完成需要传达给线程 B,但必须在线程 A 上发出同步命令。因此,如果线程 A 使用glFinish,它现在必须使用一些 CPU 同步来将线程完成传达给线程 B。如果你改用栅栏同步对象,您需要在线程 A 上创建栅栏,然后将其交给线程 B,线程 B 可以在该栅栏上测试/等待。

  2. 该对象必须重新绑定到线程 B 的上下文。也就是说,您必须在命令完成后将其绑定到该上下文(直接使用glBind*命令或通过绑定具有此对象的容器对象间接绑定到它)。

这在 OpenGL 规范的第 5 章中有详细说明。

于 2020-09-17T13:50:05.230 回答