为什么glDeleteBuffers和glDeleteVertexArrays这么慢?

问题描述 投票:0回答:1

在我的程序流程中的某个时刻,我生成0到300个网格之间的任何位置,每个网格都是这样的:

public Mesh(float[] vertices, byte[] indices, float[] textureCoordinates)
{
    vao = glGenVertexArrays();
    glBindVertexArray(vao);

    vbo = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(vertices), GL_STATIC_DRAW);
    glVertexAttribPointer(ShaderProgram.VERTEX_ATTRIB, 3, GL_FLOAT, false, 0, 0);
    glEnableVertexAttribArray(ShaderProgram.VERTEX_ATTRIB);

    tbo = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, tbo);
    glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(textureCoordinates), GL_STATIC_DRAW);
    glVertexAttribPointer(ShaderProgram.TCOORD_ATTRIB, 2, GL_FLOAT, false, 0, 0);
    glEnableVertexAttribArray(ShaderProgram.TCOORD_ATTRIB);

    ibo = glGenBuffers();
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, BufferUtils.createByteBuffer(indices), GL_STATIC_DRAW);

    glBindVertexArray(0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

当用户按下按钮时,需要再次删除这些网格,因此我对每个网格对象运行一个清理方法:

public void cleanup()
{
        glDeleteBuffers(vbo);
        glDeleteBuffers(tbo);
        glDeleteBuffers(ibo);
        glDeleteVertexArrays(vao);
}

问题是我试图以60 fps运行并删除70个这些网格对象需要大约30 ms(并删除其中的110个需要75 ms)。这会在性能上产生明显的打嗝,因为一帧最多需要16毫秒。

这不是处理VBO和VAO的正确方法吗?我读了一个不同的问题(glDeleteBuffers slower than glBufferData

glGenBuffers和glDeleteBuffers分别只在初始化和清理时运行。在运行时调用它们很糟糕。

但我不知道如何在不调用上述功能的情况下摆脱这些VBO和VAO。

我曾想过将所有要删除的网格添加到队列中,并且每帧只删除其中几个,慢慢清空队列,但这不是正确的解决方案。我想到的另一个(可能的)解决方案是使用实例化渲染,但据我所知,当我每帧进行1000次绘制调用时,非实例渲染也应该正常工作。我的程序在任何给定时间都不会有超过1000个Mesh对象,我甚至不确定这会解决我的问题。

更新:除了下面的答案指向我正确的方向,我还发现我实际上并没有删除〜0-300 VBO,而是多了48倍!难怪表演被杀死了。因此,如果其他人遇到同样的问题,请彻底检查代码执行的glDeleteBuffers的数量。

opengl lwjgl vbo vao
1个回答
3
投票

你在那里遇到了一些心理障碍。你似乎认为“per mesn:{one vertex attribute == one VBO}”,但这并不是它应该如何工作的。你应该做的是使用一个单独的大型VBO并用作一个内存池,你可以从中分配块,每个块都包含一些数据。

因此,您不仅将单个网格的所有顶点属性放入一个公共VBO中,还将几​​个网格放入一个VBO中。

此外,您似乎在每次渲染迭代中创建和删除VBO和VAO。为什么?网格在每一帧之间都会发生戏剧性的变化吗?如果是这样,那一定是癫痫诱发观察;烘焙到几何数据中的网格变形不需要重新创建缓冲区,只需使用glBufferSubData覆盖数据。

© www.soinside.com 2019 - 2024. All rights reserved.