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


推荐阅读
  • JUC并发编程——线程的基本方法使用
    目录一、线程名称设置和获取二、线程的sleep()三、线程的interrupt四、join()五、yield()六、wait(),notify(),notifyAll( ... [详细]
  • Flutter 核心技术与混合开发模式深入解析
    本文深入探讨了 Flutter 的核心技术,特别是其混合开发模式,包括统一管理模式和三端分离模式,以及混合栈原理。通过对比不同模式的优缺点,帮助开发者选择最适合项目的混合开发策略。 ... [详细]
  • Beetl是一款先进的Java模板引擎,以其丰富的功能、直观的语法、卓越的性能和易于维护的特点著称。它不仅适用于高响应需求的大型网站,也适合功能复杂的CMS管理系统,提供了一种全新的模板开发体验。 ... [详细]
  • 流处理中的计数挑战与解决方案
    本文探讨了在流处理中进行计数的各种技术和挑战,并基于作者在2016年圣何塞举行的Hadoop World大会上的演讲进行了深入分析。文章不仅介绍了传统批处理和Lambda架构的局限性,还详细探讨了流处理架构的优势及其在现代大数据应用中的重要作用。 ... [详细]
  • 本文将深入探讨 Unreal Engine 4 (UE4) 中的距离场技术,包括其原理、实现细节以及在渲染中的应用。距离场技术在现代游戏引擎中用于提高光照和阴影的效果,尤其是在处理复杂几何形状时。文章将结合具体代码示例,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 协程作为一种并发设计模式,能有效简化Android平台上的异步代码处理。自Kotlin 1.3版本引入协程以来,这一特性基于其他语言的成熟理念,为开发者提供了新的工具,以增强应用的响应性和效率。 ... [详细]
  • 视觉Transformer综述
    本文综述了视觉Transformer在计算机视觉领域的应用,从原始Transformer出发,详细介绍了其在图像分类、目标检测和图像分割等任务中的最新进展。文章不仅涵盖了基础的Transformer架构,还深入探讨了各类增强版Transformer模型的设计思路和技术细节。 ... [详细]
  • D17:C#设计模式之十六观察者模式(Observer Pattern)【行为型】
    一、引言今天是2017年11月份的最后一天,也就是2017年11月30日,利用今天再写一个模式,争取下个月(也就是12月份& ... [详细]
  • 深入理解线程池及其基本实现
    本文探讨了线程池的概念、优势及其在Java中的应用。通过实例分析不同类型的线程池,并指导如何构建一个简易的线程池。 ... [详细]
  • td{border:1pxsolid#808080;}参考:和FMX相关的类(表)TFmxObjectIFreeNotification ... [详细]
  • 本文详细介绍了 `org.apache.tinkerpop.gremlin.structure.VertexProperty` 类中的 `key()` 方法,并提供了多个实际应用的代码示例。通过这些示例,读者可以更好地理解该方法在图数据库操作中的具体用途。 ... [详细]
  • 问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ... [详细]
  • 洛谷 P4009 汽车加油行驶问题 解析
    探讨了经典算法题目——汽车加油行驶问题,通过网络流和费用流的视角,深入解析了该问题的解决方案。本文将详细阐述如何利用最短路径算法解决这一问题,并提供详细的代码实现。 ... [详细]
  • 精选10款Python框架助力并行与分布式机器学习
    随着神经网络模型的不断深化和复杂化,训练这些模型变得愈发具有挑战性,不仅需要处理大量的权重,还必须克服内存限制等问题。本文将介绍10款优秀的Python框架,帮助开发者高效地实现分布式和并行化的深度学习模型训练。 ... [详细]
  • 深入探讨:Actor模型如何解决并发与分布式计算难题
    在现代软件开发中,高并发和分布式系统的设计面临着诸多挑战。本文基于Akka最新文档,详细探讨了Actor模型如何有效地解决这些挑战,并提供了对并发和分布式计算的新视角。 ... [详细]
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社区 版权所有