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

7

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

我已经尝试了三种保存和渲染网格的方法。

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

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

并使用glDrawArrays()绘制它。

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

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

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

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

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

现在,在相同的ISO值下,我获得的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?


1
你的FPS测量方法是否考虑了使用Thrust删除冗余顶点所需的时间? - m.s.
@m.s. 只需要进行一次删除操作。我不需要实时删除方法。当等值线值被改变时,我只需在方法1中渲染粗略网格。一旦更改是恒定的,我就会处理删除,这需要大约4秒钟。之后,我只需使用VBO/IBO来渲染网格。当我测量FPS时,我希望这个网格有更高的FPS,而且只是渲染,没有提取或压缩。 - Harish
1个回答

2

有两件事情可以帮助:


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接