什么时候VBO比“简单”的OpenGL原语(glBegin())更快?
经过多年的关于顶点缓冲区对象(VBOs)的听取,我终于决定尝试一下(我的东西通常不是性能的关键,显然…)
我将在下面描述我的实验,但是为了简单起见,我在“简单”直接模式(glBegin()/ glEnd()),顶点数组(CPU端)和VBO(GPU端)之间看到了难以区分的性能,渲染模式。 我想明白为什么会这样,在什么样的条件下,我可以期望看到维也纳各组织显着地超越了他们原始的双关语的祖先。
实验细节
对于实验,我生成了大量点的(静态)三维高斯云。 每个点都有与之相关的顶点和颜色信息。 然后,我以相当的“轨道”行为在相继的帧中围绕云端旋转相机。 再次,点是静态的,只有眼睛移动(通过gluLookAt())。 数据在任何渲染之前生成一次,并存储在两个数组中以用于渲染循环。
对于直接渲染,整个数据集呈现在单个glBegin()/ glEnd()块中,每个glColor3fv()和glVertex3fv()都包含一个单独的调用。
对于顶点数组和VBO渲染,整个数据集都是用一个glDrawArrays()调用渲染的。
然后,我简单地运行一分钟左右,然后用高性能定时器测量平均FPS。
性能结果##
如上所述,我的台式机(XP x64,8GB RAM,512 MB Quadro 1700)和我的笔记本电脑(XP32,4GB RAM,256 MB Quadro NVS 110)的性能无法区分。 然而,它的确按照预期的分数进行了缩放。 显然,我也禁用了vsync。
笔记本电脑运行的具体结果(呈现w / GL_POINTS):
在glBegin()/ glEnd():
- 1K点 – > 603 FPS
- 10K – > 401 FPS
- 100K – > 97 FPS
- 1M点 – > 14 FPS
顶点数组(CPU端):
- 1K点 – > 603 FPS
- 10K – > 402 FPS
- 100K – > 97 FPS
- 1M点 – > 14 FPS
顶点缓冲区对象(GPU端):
- 1K点 – > 604 FPS
- 10K – > 399 FPS
- 100K – > 95 FPS
- 1M点 – > 14 FPS
我使用GL_TRIANGLE_STRIP呈现了相同的数据,并得到了类似的难以区分的(尽pipe由于额外的光栅化而如预期的那样变慢)。 如果有人愿意,我也可以发布这些数字。 。
问题(S)
- 是什么赋予了?
- 为了实现维也纳各组织承诺的业绩增长,我需要做些什么?
- 我错过了什么?
优化3D渲染有很多因素。 通常有4个瓶颈:
- CPU(创build顶点,APU调用,一切)
- 总线(CPU < – > GPU传输)
- 顶点(通过固定functionpipe线执行的顶点着色器)
- 像素(填充,片段着色器执行和rops)
你的testing给出了倾斜的结果,因为你有很多CPU(和总线),同时最大化顶点或像素的吞吐量。 VBO用于降低CPU(较less的API调用,与CPU DMA传输并行)。 既然你没有CPU绑定,他们不给你任何收益。 这是优化101.在游戏中,CPU变得宝贵,因为AI和物理等其他方面都需要CPU,而不仅仅是发出大量的API调用。 很容易看出,将顶点数据(例如3个浮点数)直接写入内存指针比调用将3个浮点数写入内存的函数快得多 – 至less可以节省调用的周期。
可能会有一些缺失的事情:
-
这是一个疯狂的猜测,但你的笔记本电脑的卡可能会缺less这种操作(即模拟它)。
-
您是否将数据复制到GPU的内存(通过
glBufferData
(具有GL_STATIC_DRAW
或GL_DYNAMIC_DRAW
参数的GL_DYNAMIC_DRAW
)或者您是否在内存中使用指向主(非GPU)数组的指针(这需要每帧复制一次,因此性能较慢) -
您是否将索引作为通过
glBufferData
和GL_ELEMENT_ARRAY_BUFFER
参数发送的另一个缓冲区?
如果这三件事情完成,性能增益很大。 对于Python(v / pyOpenGl),比数百个元素大的数组速度要快1000倍,C ++的速度要快5倍,但是在数组的50k-10m的顶点上。
这里是我的c + +的testing结果(Core2Duo / 8600GTS):
pts vbo glb/e ratio 100 3900 3900 1.00 1k 3800 3200 1.18 10k 3600 2700 1.33 100k 1500 400 3.75 1m 213 49 4.34 10m 24 5 4.80
所以即使有10m的顶点也是正常的帧率,而glB / e则是低速的。
作为一个方面说明:
以下内容不支持“直接模式”(glBegin / glEnd):
所以,如果你打算将应用程序移植到移动平台(例如iPhone),甚至不习惯它。
我在大学教授OpenGL,解释glBegin / glEnd的幻灯片上有一个很大的红色框,并带有一个额外的粗体“DO NOT USE”标题。
使用顶点数组只需要两行,从一开始就保存循环。
从阅读“红皮书”,我记得有一段话说VBOs可能会更快取决于硬件 。 一些硬件优化了这些,而另一些则没有。 有可能你的硬件没有。
14Mpoints / s并不是很多。 这是可疑的。 我们可以看到完成的代码正在执行绘图以及初始化吗? (比较那个14M / s到Slava Vishnyakov得到的240M / s(!))。 更令人怀疑的是,在1K的抽签中,下降到640K / s(相比之下,他的3.8M / s,看起来大约是3800 SwapBuffers)。
我会在testing不衡量你认为它的措施。
假设我记得这一点,我的OpenGL社区的OpenGL老师表示,他们在静态几何上会更快,这将在典型的游戏中呈现大量的时间,这将是桌椅和小静态实体。