热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何同步多线程OpenGL缓冲区访问?-HowtosynchronizemultithreadedOpenGLbufferaccess?

Ihavevertexbuffersholdingmeshesofterrainchunks.Whenevertheplayereditsterrain,themesh

I have vertex buffers holding meshes of terrain chunks. Whenever the player edits terrain, the mesh of the corresponding chunk must be regenerated and uploaded to the vertex buffer. Since regenerating the mesh takes some time, I do it in an asynchronous worker thread.

我有一个顶点缓冲,控制着地形块的网格。当玩家编辑地形时,相应块的网格必须重新生成并上载到顶点缓冲区。由于重新生成网格需要一些时间,所以我在异步工作线程中执行。

The issue is that the main threads draws the buffer in the same moment the worker thread uploads new data. That means, after the player editing the terrain, a corrupted chunk gets rendered for one frame. It just flares up once and after that, the correct buffers gets drawn.

问题是,主线程在工作线程上传新数据的同一时刻,绘制缓冲区。也就是说,在玩家编辑地形之后,一个被损坏的块被渲染成一个帧。它只会闪烁一次,然后,正确的缓冲区就会被绘制出来。

This kind of made sense to me, we shouldn't write and read the same data at the same time of course. So instead of updating the old buffer, I created a new one, filled it and swapped them. The swapping was just changing the buffer id stored within the terrain chunk struct, so that should be atomic. Hoever, that didn't help.

这对我来说是有意义的,我们不应该同时写和读同样的数据。因此,我没有更新旧的缓冲区,而是创建了一个新的缓冲区,填充并交换了它们。交换只是改变了存储在地形块结构中的缓冲id,所以应该是原子的。Hoever,没有帮助。

Due to the fact that OpenGL commands are sent to a queue on GPU, they don't have to be executed when the application on the CPU continues. So I may have swapped the buffers before the new one was actually ready.

由于OpenGL命令被发送到GPU上的一个队列,所以在CPU上的应用程序继续执行时,不需要执行它们。所以我可能在新的缓冲区已经准备好之前交换了缓冲区。

I also tried an alternative to switching the buffers, using a mutex for buffer access. The main thread locks the mutex while drawing and the worker thread locks it while uploading new buffer data. However, this didn't help either and it may be because of OpenGL's asynchronous nature, too. The main thread didn't actually draw, but just send draw commands to the GPU. On the other hand, when there really is only one command queue, uploading buffers and drawing them could never occur at the same time, does it?

我还尝试了另一种方法来切换缓冲区,使用互斥锁来进行缓冲区访问。主线程在绘图时锁定互斥对象,工作线程在上传新的缓冲区数据时锁定它。然而,这也没有帮助,这可能是因为OpenGL的异步性质。主线程并没有实际绘制,只是向GPU发送绘制命令。另一方面,当真的只有一个命令队列时,上传缓冲区和绘制它们可能不会同时发生,对吗?

How can I synchronize the vertex buffer access from my two threads to prevent that an undefined buffer gets drawn for one frame?

如何使两个线程的顶点缓冲区访问同步,以防止为一个框架绘制未定义的缓冲区?

1 个解决方案

#1


5  

You must make sure that the buffer update is actually completed before you can use that buffer in your draw thread. The easieast solution would be to call glFinish in your update thread after you issued all the update GL commands, and only notify the the draw thread after that returned.

您必须确保缓冲区更新实际上已经完成,然后才能在绘制线程中使用该缓冲区。在您发布了所有更新GL命令之后,easyeast解决方案将在您的更新线程中调用glFinish,并且只在返回后通知绘制线程。

To have a more fine grained control over the synchronization, I would advice you to have a look at fence sync objects (as described in the GL_ARB_sync extension). You can issue a fence sync after you issued your update commands and actually store the sync object handle with your buffer handle so that the draw thread can check if the update actually completed (or wait for it). Note that sync objects are kind of special since they are the only objects not tied to the GL context, so that they can be used in multi-context setups.

为了对同步进行更细粒度的控制,我建议您查看fence sync对象(如GL_ARB_sync扩展中所描述的)。在发出更新命令后,您可以发出一个fence sync,并将同步对象句柄与缓冲句柄存储在一起,以便绘制线程可以检查更新是否已经完成(或者等待它)。注意,同步对象是特殊的,因为它们是与GL上下文无关的唯一对象,因此它们可以在多上下文环境中使用。


推荐阅读
author-avatar
跳花妹535
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有