【问题标题】:Is it possible to in-place resize VBOs?是否可以就地调整 VBO 的大小?
【发布时间】:2011-08-31 11:46:52
【问题描述】:

标题说明了一切,但为了清楚起见,我会添加一些额外的词。

在这种情况下,resize 的意思是:

  • 在旧 vbo 末尾获得更多存储空间
  • 将旧数据保存在最前面
  • (希望不是复制,但至少不是在 CPU 端,这意味着驱动程序应该处理这个)

编辑

至于解释更多细节并证明我的问题:
我会将(正手)未知大小的数据存储到 VBO,但我只知道一个非常粗略估计的上限(在不寻常的条件下是 10 - 100 倍甚至更多)。

当然,我知道我存储了多少数据,当我完成数据时,最好先存储数据,直到我发现我的 VBO 太小,然后调整它的大小,然后继续存储。

这就是我不想复制的原因(尤其是在 CPU 端):
我在 GPU 上执行所有这些操作以获得交互式帧速率。当我必须复制时,它非常慢甚至不可能,因为没有足够的空间。最糟糕的是通过 CPU 复制数据,从而通过总线将所有内容传递到具有足够大小的新内存区域,然后 glBufferDataing VBO 以新大小和新内存区域作为源。那将是性能杀手。

规避

我通过精确估计所需空间来规避这个问题。但我会让这个问题在一周内无人回答,看看是否有人对此有其他提示,因为我对解决方案不太满意。

【问题讨论】:

  • 您是否尝试只使用一个(且巨大的)VBO?
  • @Rookie:我想让 VBO 尽可能小,但它仍然可以很大(>100mb)。但我想并行存储至少 3 个,以及一些大约 40mb 大小的额外数据。
  • 我不确定不同卡之间的 VBO 性能如何变化,但是在我的卡上我可以制作最大 1MB VBO,否则我会损失很多性能。考虑 100MB VBO 听起来很疯狂。尝试将它们分成最大 1MB 的部分,我认为即使有 100 倍以上的 VBO(在你的情况下只有 300 个 VBO),你也不会渲染任何东西。这也应该解决您的调整大小问题。更不用说:在我的卡中我不能超过 4MB 或其他东西,之后数据被破坏并且不会呈现其余部分。
  • @Rookie:对我来说,那些大的 VBO 不是问题,它们渲染得很好,没有损坏数据或减速。你的卡几岁了?我认为调用 300 次 glDrawArrays 比在大型 VBO 上调用一次开销更大,但我没有对此进行测试。
  • 如果你没有测试它,你应该......也许你的卡太快了,以至于你认为即使你只有 1% 的性能也没有减速;)我的卡不是最好的市场,但它非常好,任何游戏都可以正常工作。如果您只是为自己做这件事,那么其他人是否无法运行您的程序也没关系,否则您应该运行大量测试它在不同用户上的执行情况,我认为我无法运行那件事,甚至可能会爆炸我的卡... ;)

标签: opengl vbo


【解决方案1】:

我认为如果不进行复制,您将无法解决这个问题,因为调整缓冲区大小的唯一方法是调用 glBufferData,而且 IMO 无法告诉驱动程序保留旧数据。

您可能可以做的至少不将其复制到 CPU 并再次返回,为此创建某种辅助 VBO 并直接从 VBO 复制到辅助 VBO(使用 ARB_copy_buffer 扩展名),调整 VBO 的大小并将其内容复制回来。

但我认为最好的方法是预先分配一个更大的缓冲区,因此调整大小不是必需的,但是在这种情况下,您当然需要知道大约需要多少额外的存储空间。

【讨论】:

  • 如果您需要动态调整 VBO 的大小,您可以尝试模仿 std::vector 的行为,并在添加元素时获得装甲化的恒定时间。
  • 我也想过这个问题,但是 GPU 内存 (1GB) 的负载很重,所以没有多少空间可以容纳额外的副本。我记得根据实现阅读调整大小。驱动程序可以调整大小,但不是必须的。顺便提一句。问候~rauc ;)
  • 我忘记了大缓冲区:我必须为我不知道但只能估计的数据分配缓冲区。估计给我的分配大小比需要的大约 100 倍,但我以前不能说。因此,在这种情况下,我还必须调整大小(缩小比例)以免浪费那么多内存,正如我已经说过的那样,这种情况很少见。
【解决方案2】:

几年后重新审视这个问题,随着新版本和扩展的出现,情况发生了一些变化。

GPU 侧复制

Christian Rau 的回答中提到的扩展是自 3.1 以来的核心,它允许我们将内容(通过glCopyBufferSubData)从一个 VBO 复制到另一个。希望驱动程序在 GPU 端执行此操作!

使用这个函数,我们可以创建一个更大的缓冲区并复制前导数据。这样做的缺点是内存需求增加了一倍,因为我们需要两个缓冲区。

真正调整大小

好消息是:有了sparse buffers,一个更好的解决方案即将出现。

有了这个扩展,我们可以为我们的数据分配一个足够空间的虚拟缓冲区,而无需为不需要的空间付费。我们只需要“提交”我们物理上想要存储数据的内存区域。这意味着我们可以通过在其末尾提交新页面来“增长”VBO。

坏消息是:在当前的 OpenGL 版本 (4.5) 中,这仍然是一个扩展,还不是核心,因此采用它可能是不可能的。您也不应该认为规范中有一些尚未制定的细节。例如,当前扩展中不允许映射稀疏缓冲区,但可能会在未来版本中添加支持。

如果您有任何相关数据,我很想知道此扩展程序的可用性。

【讨论】:

    【解决方案3】:

    假设您支持最新的 OpenGL 标准,VBO 的替代方案可能是将您的数据存储在纹理中(同样,假设您的卡上有足够的内存)。在新旧纹理之间复制数据将在卡上进行,不会影响数据传输。

    实现这一点的具体方式取决于您的代码在做什么。但原则上,您使用纹理数据来覆盖绘图调用中的虚拟顶点数据,或者可能使用实例化。这需要大量的思考和返工。

    【讨论】:

      猜你喜欢
      • 2012-02-04
      • 1970-01-01
      • 2018-11-05
      • 2018-09-14
      • 1970-01-01
      • 2011-01-19
      • 1970-01-01
      • 2017-11-06
      • 1970-01-01
      相关资源
      最近更新 更多