如何优化 VBO/IBO 以最大化 GPU 缓存使用率

Posted

技术标签:

【中文标题】如何优化 VBO/IBO 以最大化 GPU 缓存使用率【英文标题】:How to Optimizing a VBO/IBO to maximize GPU cache usage 【发布时间】:2015-09-22 21:54:18 【问题描述】:

我正在使用在 CUDA 上运行的 Marching Cubes 算法从体积数据生成网格。

我尝试过保存网格并以 3 种方式渲染它。

    将一组粗略的三角形保存为顶点数据的连续数组。 如果第一次通过,我估计大小,创建一个 OpenGL VBO, 将其映射到 CUDA 并按以下格式将顶点数据写入其中

V0x, V0y, V0z, N0x, N0y, N0z, V1x, V1y, V1z, N1x, N1y, N1z, ...

并使用glDrawArrays() 绘制它。

VBO 中的冗余顶点,每个立方体的冗余顶点,无索引。

    从步骤 1 中获取网格,使用 thrust::sort()thrust::unique() 删除冗余顶点,使用 thrust::lower_bound() 计算索引。将结果保存到映射到 CUDA 的 OpenGL VBO/IBO。 使用glDrawElements() 绘制模型。

VBO 中没有冗余顶点,生成索引。

    为每个立方体生成一个唯一的顶点列表,将它们连同在 IBO 中形成三角形的索引一起存储在 VBO 中。使用 glDrawElements() 渲染。

VBO 中的冗余顶点、每个立方体的唯一顶点、每个立方体生成的索引

现在我在相同 ISO-Value ` 下获得的相同数据集的 FPS 是

Method 1 : 92  FPS, 30,647,016 Verts,          0 Indices
Method 2 : 122 FPS,  6,578,066 Verts, 30,647,016 Indices
Method 3 : 140 FPS, 20,349,880 Verts, 30,647,016 Indices

即使方法 2 产生的顶点数量最少,FPS 也很低。我相信这是因为索引的顺序可以最大限度地减少 GPU 缓存的使用。方法 3 的索引顺序获得更高的 GPU 缓存使用率,因此 FPS 更高。

如何修改/修改方法 2 以产生更高的 FPS?

【问题讨论】:

你的 FPS 测量方法是否考虑到使用推力去除冗余顶点所需的时间? @m.s.删除只进行一次。我不是在寻找实时删除方法。当 iso 值发生变化时,我只是在方法 1 中渲染粗网格。一旦变化保持不变,我就会处理大约需要 4 秒的移除。之后我只使用 VBO/IBO 来渲染网格。我希望这个网格有更高的 FPS,而只是渲染,当我测量 FPS 时不进行提取或压缩。 【参考方案1】:

有两件事可以提供帮助:

尝试通过将顶点大致按照绘制它们的顺序来优化数据缓存的使用 正在尝试优化post transform cache 的使用(here 有一个算法可以做到这一点,网上可能可以找到实现)

【讨论】:

谢谢@Jerem,我会试试这个算法Fast Vertex Cache Opt。将更新结果如何。我想找到一些使用尽可能少内存的算法,因为我的网格尺寸往往会变得非常大。 尝试了上述算法的 CPU 实现,它可以工作,但速度太慢。 60K 网格需要超过 12 秒,我的网格超过 20M,对于这种尺寸的网格来说是不可行的。正在寻找一种可扩展到 GPU 的解决方案。 您是否尝试按照绘制顺序对顶点进行排序? 嗯,是的,我在排序数百万个顶点时遇到了其他问题。如果我在 GPU 上执行它并且在 CPU 上太慢,我会遇到内存限制。但是你的答案是正确的以获得最佳的缓存命中率,但是由于网格大小,我将它用于我的应用程序是不可行的。不过我会接受这个答案。谢谢。 答案包含死链接。

以上是关于如何优化 VBO/IBO 以最大化 GPU 缓存使用率的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 VBO 和/或 IBO 而不是简单的顶点数据?

VAO 中的 C++ GLSL 多个 IBO

在 Android 上的 OpenGL ES 2.0 中使用 VBO/IBO

两个不同的对象 OpenGL。 VAO VBO IBO 网格变形问题

OpenGL中的顶点限制

如何优化这个 Haskell 程序?