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


推荐阅读
  • 本文探讨了如何通过一系列技术手段提升Spring Boot项目的并发处理能力,解决生产环境中因慢请求导致的系统性能下降问题。 ... [详细]
  • 主板IO用W83627THG,用VC如何取得CPU温度,系统温度,CPU风扇转速,VBat的电压. ... [详细]
  • 本文详细介绍了Java中实现异步调用的多种方式,包括线程创建、Future接口、CompletableFuture类以及Spring框架的@Async注解。通过代码示例和深入解析,帮助读者理解并掌握这些技术。 ... [详细]
  • dotnet 通过 Elmish.WPF 使用 F# 编写 WPF 应用
    本文来安利大家一个有趣而且强大的库,通过F#和C#混合编程编写WPF应用,可以在WPF中使用到F#强大的数据处理能力在GitHub上完全开源Elmis ... [详细]
  • 本文介绍如何使用布局文件在Android应用中排列多行TextView和Button,使其占据屏幕的特定比例,并提供示例代码以帮助理解和实现。 ... [详细]
  • 本文详细介绍了在 Windows 2000 系统中启用 TELNET 服务时需要注意的 NTLM 配置问题,帮助用户解决常见的身份验证失败错误。 ... [详细]
  • 本文详细介绍了在不同操作系统中查找和设置网卡的方法,涵盖了Windows系统的具体步骤,并提供了关于网卡位置、无线网络设置及常见问题的解答。 ... [详细]
  • 本文详细介绍了Grand Central Dispatch (GCD) 的核心概念和使用方法,探讨了任务队列、同步与异步执行以及常见的死锁问题。通过具体示例和代码片段,帮助开发者更好地理解和应用GCD进行多线程开发。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 本文介绍了如何在 C# 和 XNA 框架中实现一个自定义的 3x3 矩阵类(MMatrix33),旨在深入理解矩阵运算及其应用场景。该类参考了 AS3 Starling 和其他相关资源,以确保算法的准确性和高效性。 ... [详细]
  • 并发编程 12—— 任务取消与关闭 之 shutdownNow 的局限性
    Java并发编程实践目录并发编程01——ThreadLocal并发编程02——ConcurrentHashMap并发编程03——阻塞队列和生产者-消费者模式并发编程04——闭锁Co ... [详细]
  • Linux环境下进程间通信:深入解析信号机制
    本文详细探讨了Linux系统中信号的生命周期,从信号生成到处理函数执行完毕的全过程,并介绍了信号编程中的注意事项和常见应用实例。通过分析信号在进程中的注册、注销及处理过程,帮助读者理解如何高效利用信号进行进程间通信。 ... [详细]
  • 本题要求在一组数中反复取出两个数相加,并将结果放回数组中,最终求出最小的总加法代价。这是一个经典的哈夫曼编码问题,利用贪心算法可以有效地解决。 ... [详细]
  • 本文详细介绍如何使用 Apache Spark 执行基本任务,包括启动 Spark Shell、运行示例程序以及编写简单的 WordCount 程序。同时提供了参数配置的注意事项和优化建议。 ... [详细]
  • 本文深入探讨了UNIX/Linux系统中的进程间通信(IPC)机制,包括消息传递、同步和共享内存等。详细介绍了管道(Pipe)、有名管道(FIFO)、Posix和System V消息队列、互斥锁与条件变量、读写锁、信号量以及共享内存的使用方法和应用场景。 ... [详细]
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社区 版权所有