在 OpenGL 上下文之间同步资源时是否需要调用 glFinish?

Eba*_*sin 5 opengl vbo openglcontext

我在我的应用程序中使用了两个 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?)

另外,是否有文档或参考文献讨论过这个问题?我找不到任何提及,并且在实现之间的工作方式似乎有所不同。

Nic*_*las 5

如果您在线程 A 中操作任何对象的内容,那么在发生以下两件事之前,其他线程 B 将看不到这些内容:

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

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

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

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