我是否可以在 OpenGL 2.1 中的多个共享上下文中同时从同一个缓冲区对象进行渲染?
Am I allowed to simultaneously render from the same buffer object on multiple shared contexts in OpenGL 2.1?
在 Apple 的文档中,我读到:
- 1 — "Shared contexts share all texture objects, display lists, vertex programs, fragment programs, and buffer objects created before and after sharing is initiated."
- 2 — "Contexts that are on different threads can share object resources. For example, it is acceptable for one context in one thread to modify a texture, and a second context in a second thread to modify the same texture. The shared object handling provided by the Apple APIs automatically protects against thread errors."
所以我希望能够一次创建我的缓冲区对象,然后使用它们在多个上下文中同时呈现。但是,如果我这样做,我的 NVIDIA GeForce GT 650M 会崩溃,回溯如下:
Crashed Thread: 10 Dispatch queue: com.apple.root.default-qos
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: EXC_I386_GPFLT
…
Thread 10 Crashed:: Dispatch queue: com.apple.root.default-qos
0 GLEngine 0x00007fff924111d7 gleLookupHashObject + 51
1 GLEngine 0x00007fff925019a9 gleBindBufferObject + 52
2 GLEngine 0x00007fff9243c035 glBindBuffer_Exec + 127
我已经在 https://gist.github.com/jlstrecker/9df10ef177c2a49bae3e 上发布了我的完整代码。在顶部,有 #define SHARE_BUFFERS
— 当注释掉时它工作得很好,但取消注释时它崩溃了。
我不想争论我是否应该使用 OpenGL 2.1 — 这是我正在使用的其他软件的要求。我也不想争论我是否应该使用 GLUT — 我的示例代码只是使用它,因为它包含在 Mac 中并且没有任何外部依赖性。我也不是在寻找关于 performance/optimization.
的反馈
我只想知道我是否可以期望能够在多个上下文中同时从单个共享缓冲区对象进行渲染 — 如果是这样,我的代码为什么会崩溃。
我们还 运行 调查了 'gleLookupHashObject' 崩溃并制作了一个小的重现案例(与您的案例非常相似),该案例已发布在 'incident' Apple 支持中。经过调查,一位 Apple DTS 工程师返回了以下信息,引用:
“我注意到 glFlush() 在主线程和绑定位置数据的辅助线程上都被调用。这确实会引入问题,虽然微妙,但实际上确实表明我们的约束放在线程上,GL 上下文没有得到充分尊重。
在这一点上,您应该进一步研究您的实现以确保避免此类情况,或者更好的是,使用显式同步机制(例如我们提供的 GCD)扩展您的实现。 “
因此,如果您 运行 遇到此崩溃,您将需要在应用程序端进行显式同步(等待驱动程序端的修复)。
Apple 官方文档中与 "OpenGL, Contexts and Threading" 相关的相关片段摘要:
[0] Section: "Use Multiple OpenGL Contexts"
If your application has multiple scenes that can be rendered in parallel, you can use a context for each scene you need to render. Create one context for each scene and assign each context to an operation or task. Because each task has its own context, all can submit rendering commands in parallel.
https://developer.apple.com/library/mac/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_threading/opengl_threading.html#//apple_ref/doc/uid/TP40001987-CH409-SW6
[1] Section: Guidelines for Threading OpenGL Applications
(a) Use only one thread per context. OpenGL commands for a specific context are not thread safe. You should never have more than one thread accessing a single context simultaneously.
(b) Contexts that are on different threads can share object resources. For example, it is acceptable for one context in one thread to modify a texture, and a second context in a second thread to modify the same texture. The shared object handling provided by the Apple APIs automatically protects against thread errors. And, your application is following the "one thread per context" guideline.
https://developer.apple.com/library/mac/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_threading/opengl_threading.html
[2] OpenGL Restricts Each Context to a Single Thread
Each thread in an OS X process has a single current OpenGL rendering context. Every time your application calls an OpenGL function, OpenGL implicitly looks up the context associated with the current thread and modifies the state or objects associated with that context.
OpenGL is not reentrant. If you modify the same context from multiple threads simultaneously, the results are unpredictable. Your application might crash or it might render improperly. If for some reason you decide to set more than one thread to target the same context, then you must synchronize threads by placing a mutex around all OpenGL calls to the context, such as gl* and CGL*. OpenGL commands that blockâsuch as fence commandsâdo not synchronize threads.
https://developer.apple.com/library/mac/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_threading/opengl_threading.html
在 Apple 的文档中,我读到:
- 1 — "Shared contexts share all texture objects, display lists, vertex programs, fragment programs, and buffer objects created before and after sharing is initiated."
- 2 — "Contexts that are on different threads can share object resources. For example, it is acceptable for one context in one thread to modify a texture, and a second context in a second thread to modify the same texture. The shared object handling provided by the Apple APIs automatically protects against thread errors."
所以我希望能够一次创建我的缓冲区对象,然后使用它们在多个上下文中同时呈现。但是,如果我这样做,我的 NVIDIA GeForce GT 650M 会崩溃,回溯如下:
Crashed Thread: 10 Dispatch queue: com.apple.root.default-qos
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: EXC_I386_GPFLT
…
Thread 10 Crashed:: Dispatch queue: com.apple.root.default-qos
0 GLEngine 0x00007fff924111d7 gleLookupHashObject + 51
1 GLEngine 0x00007fff925019a9 gleBindBufferObject + 52
2 GLEngine 0x00007fff9243c035 glBindBuffer_Exec + 127
我已经在 https://gist.github.com/jlstrecker/9df10ef177c2a49bae3e 上发布了我的完整代码。在顶部,有 #define SHARE_BUFFERS
— 当注释掉时它工作得很好,但取消注释时它崩溃了。
我不想争论我是否应该使用 OpenGL 2.1 — 这是我正在使用的其他软件的要求。我也不想争论我是否应该使用 GLUT — 我的示例代码只是使用它,因为它包含在 Mac 中并且没有任何外部依赖性。我也不是在寻找关于 performance/optimization.
的反馈我只想知道我是否可以期望能够在多个上下文中同时从单个共享缓冲区对象进行渲染 — 如果是这样,我的代码为什么会崩溃。
我们还 运行 调查了 'gleLookupHashObject' 崩溃并制作了一个小的重现案例(与您的案例非常相似),该案例已发布在 'incident' Apple 支持中。经过调查,一位 Apple DTS 工程师返回了以下信息,引用:
“我注意到 glFlush() 在主线程和绑定位置数据的辅助线程上都被调用。这确实会引入问题,虽然微妙,但实际上确实表明我们的约束放在线程上,GL 上下文没有得到充分尊重。 在这一点上,您应该进一步研究您的实现以确保避免此类情况,或者更好的是,使用显式同步机制(例如我们提供的 GCD)扩展您的实现。 “
因此,如果您 运行 遇到此崩溃,您将需要在应用程序端进行显式同步(等待驱动程序端的修复)。
Apple 官方文档中与 "OpenGL, Contexts and Threading" 相关的相关片段摘要:
[0] Section: "Use Multiple OpenGL Contexts"
If your application has multiple scenes that can be rendered in parallel, you can use a context for each scene you need to render. Create one context for each scene and assign each context to an operation or task. Because each task has its own context, all can submit rendering commands in parallel.
https://developer.apple.com/library/mac/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_threading/opengl_threading.html#//apple_ref/doc/uid/TP40001987-CH409-SW6
[1] Section: Guidelines for Threading OpenGL Applications
(a) Use only one thread per context. OpenGL commands for a specific context are not thread safe. You should never have more than one thread accessing a single context simultaneously.
(b) Contexts that are on different threads can share object resources. For example, it is acceptable for one context in one thread to modify a texture, and a second context in a second thread to modify the same texture. The shared object handling provided by the Apple APIs automatically protects against thread errors. And, your application is following the "one thread per context" guideline.
https://developer.apple.com/library/mac/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_threading/opengl_threading.html
[2] OpenGL Restricts Each Context to a Single Thread
Each thread in an OS X process has a single current OpenGL rendering context. Every time your application calls an OpenGL function, OpenGL implicitly looks up the context associated with the current thread and modifies the state or objects associated with that context.
OpenGL is not reentrant. If you modify the same context from multiple threads simultaneously, the results are unpredictable. Your application might crash or it might render improperly. If for some reason you decide to set more than one thread to target the same context, then you must synchronize threads by placing a mutex around all OpenGL calls to the context, such as gl* and CGL*. OpenGL commands that blockâsuch as fence commandsâdo not synchronize threads.
https://developer.apple.com/library/mac/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_threading/opengl_threading.html