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