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