gpt4 book ai didi

c++ - 为什么 VBO 顶点大小与用户/系统 CPU 时间使用量成正比?

转载 作者:太空宇宙 更新时间:2023-11-04 04:59:58 24 4
gpt4 key购买 nike

我编写了一个简单的基准测试来了解 VBO 的使用情况。从逻辑上来说,它的作用非常简单:

  1. 从文件加载 WaveFront 对象(我测试过 Stanford BunnyStanford DragonHappy Buddha )
  2. 创建并初始化 3 个 VBO(一个用于顶点、法线和索引)
  3. 通过调用一次次(针对每个实例)来渲染场景:


// enable states
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
// bind vertexes
glBindBuffer(GL_ARRAY_BUFFER, vbos_[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
// normal
glBindBuffer(GL_ARRAY_BUFFER, vbos_[1]);
glNormalPointer(GL_FLOAT, 0, 0);
// indexes
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos_[2]);
// draw n_i_ triangles using offset of index array
glDrawElements(GL_TRIANGLES, n_i_, GL_UNSIGNED_INT, 0);
// deactivate vertex array
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
// bind with 0, so, switch back to normal pointer operation
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

  • 外部循环如下(sceneVBO 告诉要绘制多少个相同的实例):


  • for(const auto& i : sceneVBO) {
    glPushMatrix();
    glColor3fv(i.rgb);
    glTranslatef(i.posX, 0.0f, i.posZ);
    glRotatef(angle*i.r_speed, 0.0f, 1.0f, 0.0f);
    vboTest->draw(); // Executes step 3
    glPopMatrix();
    }

  • 我已经开始总体测量 FPS 和性能,我观察到 VBO 包含的三角形越多,渲染循环期间用户系统花费的时间就越长;请注意,我用 getrusage 测量了用户/系统时间
  • 下面是一些引用编号(w/u/s 是 wall/user/system 的计时,以 msec 为单位)。
    对于此测试,我渲染了 100 个实例完全相同的 VBO(即 sceneVBO 包含 100 个元素,所有这些元素都引用非常相同 3 个 VBO - 顶点、法线和索引)。

    • Bunny 已加载 [bunny.obj] 34835/69666(Tris/Vertexes)
      FPS: 333.3 CPU (ms/frame): 3.0/0.8/2.0 (w/u/s) 总时间 (ms): 14999.5/4000.4/10000.2 (w/u/s) 帧数: 5000
    • 已加载[dragon.obj] 50000/100000(Tris/Vertexes)
      FPS: 217.4 CPU (ms/frame): 4.6/1.4/3.0 (w/u/s) 总时间 (ms): 22999.6/6999.7/15000.9 (w/u/s) 帧数: 5000
    • Buddha 已加载 [buddha.obj] 543524/1087474(Tris/Vertexes)
      FPS: 27.5 CPU (ms/frame): 36.4/10.4/26.0 (w/u/s) 总时间 (ms): 181999.9/51999.8/130000.3 (w/u/s) 帧数: 5000

    因此我的问题是,为什么 VBO 顶点大小与用户/系统 CPU 时间成正比?

    我知道如果 GPU 有更多的三角形要绘制,则需要更长的时间,但为什么要花费更多的 CPU 用户/系统时间?
    我不会重新发送每一帧的顶点/法线或索引 - 所有应该都保存在 GPU 内存中(数组缓冲区用 GL_STATIC_DRAW 填充) - 我预计绘制帧需要更长的时间,但 CPU 使用率相对较低(用户和系统)。

    或者驱动程序 (nVidia 352.63)/GL 是否在 glXSwapBuffers 上处于事件状态?

    我预计w所有时间都会增加,但坦率地说没有用户服务器和系统系统时间...

    诗。当然垂直同步被禁用。

    最佳答案

    您的代码中有一些内容可能值得怀疑。

    您正在使用立即模式,这意味着您的 API 调用依赖于已弃用的行为,而您的驱动程序可能对这些行为进行了糟糕的优化。

    // enable states
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    // bind vertexes
    glBindBuffer(GL_ARRAY_BUFFER, vbos_[0]);
    glVertexPointer(3, GL_FLOAT, 0, 0);
    // normal
    glBindBuffer(GL_ARRAY_BUFFER, vbos_[1]);
    glNormalPointer(GL_FLOAT, 0, 0);
    // indexes
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos_[2]);
    // draw n_i_ triangles using offset of index array
    glDrawElements(GL_TRIANGLES, n_i_, GL_UNSIGNED_INT, 0);
    // deactivate vertex array
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    // bind with 0, so, switch back to normal pointer operation
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    您强调,这段代码每个实例只调用一次,但由于 OpenGL 的工作方式,它和 DX9(OpenGL 的立即模式最相似)都不能很好地映射到显卡的实际功能,在这些用于正确设置状态的 API 调用中可能会发生很多事情。例如,您对 glVertexPointer 的调用必须设置状态以从正确的内存段中读取,如果您的缓冲区对象特别大,这可能是一个不简单的操作,因为必须为 GPU 启动以运行着色器的每个线程设置这些指针。

    Or is it that the driver (nVidia 352.63)/GL has an active spin on glXSwapBuffers?

    我也不排除这种可能性。它确实必须定期查询显卡以查明命令是否已完成执行,因此 Nvidia 可以选择将此功能实现为忙等待。

    底线是,如果您担心 OpenGL 中的 CPU 开销,您可能希望研究一些 AZDO techniques (适用于OpenGL 4.3+),或者考虑学习DirectX 12 (适用于 Windows 10)或 Vulkan (适用于 Windows 10 以外的任何系统)

    关于c++ - 为什么 VBO 顶点大小与用户/系统 CPU 时间使用量成正比?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36156772/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com