我的理解是不推荐使用多个VBO绑定调用,因为它会产生CPU的开销。但是,将几个VBO绑定到一个VAO,然后绑定VAO减少或完全消除绑定几个VBO的开销,因为你让OpenGL自动重新绑定那些VBO?这假设GPU知道该做什么,而且OpenGL不会在CPU上为你做这件事。
我已经四处寻找,但我无法得出任何结果。我目前仍然使用OpenGL< 2.1笔记本电脑,因此我无法真正测试自己(还)。
答案 0 :(得分:0)
这些事情完全是针对具体实施的。它会减少对驱动程序的一些函数调用,这可能已经值得了。但是实现如何在内部处理VAO并不是真正可预测的。当VAO被绑定时,OpenGL的设计方式仍将导致大量的验证,例如,实现将无法仅将指针缓存到内存,这是VAO设置时GPU的相关内容,因为VBO正在引用名称。由于您可以为同一个缓冲区对象创建一个新的完全不同的缓冲区存储,因此实现必须至少确保缓冲区对象仍然与之前相同。所以这里有很多东西要做,这不会发生在GPU上,所以我不希望在这种情况下CPU开销大幅下降。但是,我还没有对它进行描述......
答案 1 :(得分:0)
通过精心调整的驱动程序实现,即使使用VAO,如果所有属性都在同一个VBO中,我仍然希望它更高效。 derhass 已经触及了一个主要方面。大多数GPU无法使用CPU地址直接访问内存。缓冲区必须映射到GPU地址空间。
因此,每次绑定VAO时,驱动程序必须至少检查这些映射是否已存在,并映射尚未映射的缓冲区。还有用于跟踪绘图调用缓冲区的开销,以确保它们保持映射,直到绘制调用完成执行。您使用的缓冲区越多,所有这些都需要的工作量越多。
另一方面是存储器访问模式。如果您的属性在单个缓冲区中交错,则可以获得更好的内存访问位置。假设您有位置和法线,每个浮点数有3个浮点数,每个顶点最多可添加24个字节。如果它们是交错的,则24个字节可能位于相同的高速缓存行中。如果它们位于两个单独的缓冲区中,则单个顶点可能会出现两次缓存未命中。
关于VAO是否更有效的问题:
是的,如果能够很好地实施,那么绑定VAO应该更有效率。例如,在不使用VAO的情况下,绑定缓冲区时通常会有一堆glVertexAttribPointer
调用。传入这些调用的状态(大小,类型,步幅等)必须转换为GPU命令。使用VAO,只有在VAO发生变化时才能重建用于设置此状态的GPU命令,然后每次VAO绑定时都重复使用。
虽然普通VBO使用的状态设置也可以很好地优化,但它仍然需要在驱动程序中进行更多的工作。您还需要进行更多API调用的开销。