C# 在线程之间同步VBO的最佳方法

C# 在线程之间同步VBO的最佳方法,c#,multithreading,opengl,graphics,C#,Multithreading,Opengl,Graphics,所以我有一个类似于minecraft的区块系统,这意味着它是一块渲染数据。当玩家四处移动并输入另一个区块时,在加载新区块的同时卸载超出范围的区块,这使得它要求很高,因为在显示渲染数据之前,必须先在另一个线程中计算渲染数据 假设数据已经从磁盘加载,看起来是这样的 主/渲染线程渲染数据生成线程 | Request Chunk | | -------------------------------> | |

所以我有一个类似于minecraft的区块系统,这意味着它是一块渲染数据。当玩家四处移动并输入另一个区块时,在加载新区块的同时卸载超出范围的区块,这使得它要求很高,因为在显示渲染数据之前,必须先在另一个线程中计算渲染数据

假设数据已经从磁盘加载,看起来是这样的

主/渲染线程渲染数据生成线程

   |         Request Chunk            |
   | -------------------------------> |
   |                                  |
   |                                  | Generating render data (FloatBuffer)
   |                                  |
   |                                  .
   |                                  .
   |                                  .
   |        Get Ready Chunks          |
   | <------------------------------- |
   |                                  |
   | Upload Data                      |
   |                                  |
   | Render                           |
   |                                  |
|请求块|
| -------------------------------> |
|                                  |
||生成渲染数据(浮动缓冲区)
|                                  |
|                                  .
|                                  .
|                                  .
|准备好块|

|不幸的是,OpenGL本质上是单线程的。因此,只能从单个线程调用OpenGL。您可以在单独的线程中在后台加载块(正如阻塞I/O一样),但最终需要从OpenGL主线程将其上载到图形卡


您可以使用
glBufferSubData()
。它允许你上传一块一块的几何体,而不是一次上传所有的几何体。我不认为你能够完全摆脱挂接,因此,也许你可以尝试在加载块的同时,在每帧传输恒定数量的几何体,这样你至少可以将过程分散到多个帧上。

老实说,你限制每帧上传数量的方法可能是一条可行的道路;即使是我参与制作的商业游戏也会这样做,以避免流媒体故障。在其他线程中完成所有可能的工作,然后在渲染线程中只完成提交本身


加快这一速度的一个有用的方法可能是考虑减少每个数据块实际需要上传的数据量的方法。例如,在我自己的体素渲染器中,块大小为64x64x64,这意味着每个组件的位置只需要8位(还有几位备用)。我可以通过在像素着色器中计算导数来避免提交法线。诸如此类。

您实际上可以通过使用共享上下文在线程之间创建/共享缓冲区,例如,和。嗯,有一件事我不知道。我将对此进行研究。@BDL:根据我所阅读的内容(也在您链接的页面以外的页面上),大多数驱动程序仍会将多个上下文转换为OpenGL串行调用。因此,除了能够以牺牲OpenGL上下文切换性能为代价将资源随意上传到OpenGL之外,还有其他原因说明使用多个上下文更好吗?对我来说,在多个帧上进行流式传输和抹去资源加载似乎更好。我个人将两者兼而有之。你是绝对正确的,在幕后GPU命令必须被序列化。但在大多数情况下,操作由CPU和GPU部分组成。加载数据时,通常会有一个应用程序到驱动程序的内存复制操作和一个可能的格式转换,在多个线程并行执行的情况下,可能会涉及到该操作。共享上下文是否能提供比单一上下文更好的性能,只能根据具体情况进行分析。第28章中有一篇有趣的文章,免费下载。