热门标签 | 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上下文无关的唯一对象,因此它们可以在多上下文环境中使用。


推荐阅读
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 如何在php文件中添加图片?
    本文详细解答了如何在php文件中添加图片的问题,包括插入图片的代码、使用PHPword在载入模板中插入图片的方法,以及使用gd库生成不同类型的图像文件的示例。同时还介绍了如何生成一个正方形文件的步骤。希望对大家有所帮助。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 设计模式——模板方法模式的应用和优缺点
    本文介绍了设计模式中的模板方法模式,包括其定义、应用、优点、缺点和使用场景。模板方法模式是一种基于继承的代码复用技术,通过将复杂流程的实现步骤封装在基本方法中,并在抽象父类中定义模板方法的执行次序,子类可以覆盖某些步骤,实现相同的算法框架的不同功能。该模式在软件开发中具有广泛的应用价值。 ... [详细]
  • 本文介绍了pack布局管理器在Perl/Tk中的使用方法及注意事项。通过调用pack()方法,可以控制部件在显示窗口中的位置和大小。同时,本文还提到了在使用pack布局管理器时,应注意将部件分组以便在水平和垂直方向上进行堆放。此外,还介绍了使用Frame部件或Toplevel部件来组织部件在窗口内的方法。最后,本文强调了在使用pack布局管理器时,应避免在中间切换到grid布局管理器,以免造成混乱。 ... [详细]
  • 本文介绍了关系型数据库和NoSQL数据库的概念和特点,列举了主流的关系型数据库和NoSQL数据库,同时描述了它们在新闻、电商抢购信息和微博热点信息等场景中的应用。此外,还提供了MySQL配置文件的相关内容。 ... [详细]
  • 本文介绍了在go语言中利用(*interface{})(nil)传递参数类型的原理及应用。通过分析Martini框架中的injector类型的声明,解释了values映射表的作用以及parent Injector的含义。同时,讨论了该技术在实际开发中的应用场景。 ... [详细]
  • OpenMap教程4 – 图层概述
    本文介绍了OpenMap教程4中关于地图图层的内容,包括将ShapeLayer添加到MapBean中的方法,OpenMap支持的图层类型以及使用BufferedLayer创建图像的MapBean。此外,还介绍了Layer背景标志的作用和OMGraphicHandlerLayer的基础层类。 ... [详细]
  • Question该提问来源于开源项目:react-native-device-info/react-native-device-info ... [详细]
  • STM32 IO口模拟串口通讯
    转自:http:ziye334.blog.163.comblogstatic224306191201452833850647前阵子,调项目时需要用到低波 ... [详细]
  • 寻求更强大的身份和访问管理(IAM)平台的企业正在转向云,并接受身份即服务(IDaaS)的灵活性。要为IAM选择正确的场外解决方案,业务管理人员和IT专业人员必须在实施之前评估安全 ... [详细]
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社区 版权所有