ios - 在 iOS 中使用 Metal 渲染时每帧更新索引缓冲区

标签 ios 3d rendering metal

我有非常动态的数据,每一帧都会发生变化。数据本身比较小所以我使用

[commandEncoder setVertexBytes:_vertices.buffer() length:_vertices.size() * sizeof(float) atIndex:0];

设置顶点数据。

但是,在绘制时我还需要设置索引数据:

[commandEncoder drawIndexedPrimitives: ...];

如何更新在drawIndexedPrimitives方法中提供的用于索引数据的MTLBuffer?我需要能够有效地更新索引缓冲区。

最佳答案

This article包含对使用多个缓冲区在 CPU 和 GPU 之间同步数据而不强制它们锁步工作的深入解释。你应该仔细阅读它。我将在下面总结该方法。

  1. 为索引缓冲区选择一个足够大的大小,以容纳您可能需要绘制的最大索引数。
  2. 分配几个 (2-3) 个此大小的缓冲区并将它们放入一个数组(类型为 NSArray<id<MTLBuffer>> )中。这是你的重用池;我将其称为indexBufferPool下面。
  3. 初始化渲染器时,create a dispatch semaphore其值等于您放入重用池中的缓冲区数量。我将其称为bufferSemaphore下面。
  4. 创建一个缓冲区索引成员变量并将其初始化为0。我将其称为bufferIndex下面。
  5. 每次绘制时,通过调用 dispatch_semaphore_wait(bufferSemaphore, DISPATCH_TIME_FOREVER) 等待信号量.
  6. 当信号量等待函数返回时,可以安全地将新索引数据复制到当前缓冲区索引处的缓冲区中。使用memcpy或其他一些复制技术,将索引数据复制到 bufferPool[bufferIndex] 的内容中.
  7. 使用bufferPool[bufferIndex]绘制您的基元作为索引缓冲区。
  8. 增量bufferIndex通过设置bufferIndex = (bufferIndex + 1) % ResourceCount ,其中ResourceCount是重用池中缓冲区的数量。
  9. 在提交之前,将已完成的处理程序添加到当前命令缓冲区。完成的处理程序应调用 dispatch_semaphore_signal(bufferSemaphore) 。这让任何对绘制方法的挂起调用都知道可以安全地在当前缓冲区索引处写入缓冲区。

关于ios - 在 iOS 中使用 Metal 渲染时每帧更新索引缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59503060/

相关文章:

iphone - 从应用程序本身访问相机

objective-c - 本地通知,当应用程序处于前台时,applicationIconBadgeNumber保留

python - Matplotlib - 提取 3D 多边形图的 2D 轮廓

javascript - Google是否以错误的方式使用“延迟”?

php - 渲染 javascript 文件,同时将其作为静态文件使用

ios - 动态类型 "Body"样式在具有静态单元格的 UITableView 中不起作用

ios - 根据文本调整 UILabel 高度

html - 图像输出 rom R 分辨率低

algorithm - 如何合并网格上相邻的共面面

iphone - OpenGL ES 和现实世界的开发