标题说明了所有内容,但为了清楚起见,我会添加一些额外的单词。
在这种情况下, 调整 手段:
- 在旧的vbo结束时获得更多的存储空间
- 将旧数据保存在前面
- (希望不要复制,但至少不要在CPU端,这意味着驱动程序应该处理这个)
编辑
至于解释一些更多细节并证明我的问题:
我将(正手)未知大小的数据存储到VBO,但我只知道一个非常粗略估计的上限(在异常条件下10-100倍甚至更多)。
当然,我知道我存储了多少数据,当我完成它时,所以存储数据会很好,直到我发现我的VBO太小并重新调整它然后继续存储。
这就是为什么我不想复制(特别是不在CPU端):
我在GPU上做这一切以获得交互式帧速率。当我不得不复制时,它很慢甚至不可能,因为没有足够的空间。最糟糕的是通过CPU复制数据,从而通过总线将所有内容传递到具有足够大小的新内存区域,然后 glBufferData
使用新大小的VBO和新的内存区域作为源。那将是性能杀手。
绕开
我通过准确估计所需空间来规避问题。但是我会让这个问题在一个星期内无法回答,看看是否有人对此有另一个暗示,因为我对解决方案不太满意。
我认为没有复制你就不会解决这个问题,因为调整缓冲区的唯一方法是调用 glBufferData
并且IMO无法告诉驱动程序保留旧数据。
您可能做的至少不能将其复制到CPU并再次返回,为这些目的创建某种辅助VBO并直接从VBO复制到辅助VBO(使用 ARB_copy_buffer 扩展),调整VBO的大小并将其内容复制回来。
但我认为最好的方法是预先分配一个更大的缓冲区,因此调整大小不是必需的,但当然在这种情况下你需要知道你需要多少额外的存储空间。
多年后重新审视这个问题,新版本和扩展版本的情况发生了一些变化。
GPU端复制
Christian Rau的回答中提到的扩展是自3.1以来的核心,它允许我们复制内容(通过 glCopyBufferSubData)从一个VBO到另一个。希望驱动程序在GPU方面做到这一点!
使用此功能,我们可以创建更大的缓冲区并复制前导数据。这样做的缺点是内存需求加倍,因为我们需要两个缓冲区。
真正的大小调整
好消息是:随着 稀疏缓冲区 一个更好的解决方案即将出现。
鉴于此扩展,我们可以为数据分配一个具有足够空间的虚拟缓冲区,而无需支付不必要的空间。我们只需要“提交”我们实际想要存储数据的内存区域。这意味着我们可以通过在其末尾提交新页面来“增长”VBO。
坏消息是:截至当前的OpenGL版本(4.5),这仍然是一个扩展而不是核心,因此采用这种方法可能是不可能的。您还应该注意,规范中还有一些尚未解决的细节。例如,当前扩展中不允许映射稀疏缓冲区,但可能会在将来的版本中添加支持。
如果你有任何数据,我会很想知道这个扩展的可用性。
假设您支持最近的OpenGL标准,VBO的替代方案可能是将数据存储在纹理中(同样,假设您的卡上有足够的内存)。在新旧纹理之间复制数据将在卡上进行,而不会影响数据传输。
具体如何实现这一点取决于您的代码究竟在做什么。但原则上,您使用纹理数据覆盖绘图调用中的虚拟顶点数据,或者使用实例化。这需要大量的思考和返工。