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

时间:2016-03-22 14:13:01

标签: c++ linux opengl vbo

我已经编写了一个简单的基准来了解VBO的用法。 在逻辑方面,这样做非常简单:

  1. 从文件中加载WaveFront对象(我测试过Stanford BunnyStanford DragonHappy Buddha
  2. 创建并初始化3个VBO(一个用于顶点,法线和索引)
  3. 通过调用一个时间(对于每个实例)渲染场景:
  4. 
    
        // 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);
    
    
    1. 外部循环如下(sceneVBO告诉要绘制多少相同的实例
    2. 
      
          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();
          }
      
      
      1. 我开始测量FPS和性能一般,我观察到VBO包含的三角形越多,用户系统越长渲染循环期间花费的时间;请注意我已使用getrusage
      2. 衡量了用户/系统时间

        以下一些参考编号(w / u / s是 msec 的时间 w 所有/ u ser / s ystem)。
        对于此测试,我已经将100 实例呈现为完全相同的 VBO (即sceneVBO包含100个元素,所有那些都指向非常相同 3 VBOs - 顶点,法线和索引)。

        • Bunny Loaded [bunny.obj] 34835/69666 (Tris/Vertexes) FPS: 333.3 CPU (ms/frame): 3.0/ 0.8/ 2.0 (w/u/s) Total time (ms): 14999.5/4000.4/10000.2 (w/u/s) Frames: 5000
        • Loaded [dragon.obj] 50000/100000 (Tris/Vertexes) FPS: 217.4 CPU (ms/frame): 4.6/ 1.4/ 3.0 (w/u/s) Total time (ms): 22999.6/6999.7/15000.9 (w/u/s) Frames: 5000
        • Loaded [buddha.obj] 543524/1087474 (Tris/Vertexes) FPS: 27.5 CPU (ms/frame): 36.4/10.4/26.0 (w/u/s) Total time (ms): 181999.9/51999.8/130000.3 (w/u/s) Frames: 5000

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

        据我所知,如果GPU有更多的三角形绘制,它会花费更长的时间,但为什么需要更多的CPU用户/系统时间呢? 我没有重新发送每个帧的顶点/法线和索引 - 所有假设要保存在GPU内存中(数组缓冲区用GL_STATIC_DRAW填充) - 我原以为绘制帧的时间较长,但相对较少的CPU使用率(用户和系统)。

        或是驱动程序(nVidia 352.63)/ GL在glXSwapBuffers上有活动旋转吗?

        我一直希望 w 一直增加,但坦率地说 u ser和 s ystem time ...

        聚苯乙烯。当然 V-Sync 已被禁用。

2 个答案:

答案 0 :(得分:1)

您的代码中可能存在一些可疑内容。

您正在使用立即模式,这意味着您的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启动每个线程以运行着色器。

  

或是驱动程序(nVidia 352.63)/ GL在glXSwapBuffers上有活动旋转吗?

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

但最重要的是,如果您担心OpenGL中的CPU开销,您可能希望查看一些AZDO techniques(对于OpenGL 4.3+),或者考虑学习DirectX 12(对于Windows) 10)或Vulkan(对于任何不是Windows 10的东西)

答案 1 :(得分:0)

如上所述,我进行了以下操作:

  • 将代码移植到 GL 4.5
  • 正确使用 VAO s
  • 创建了简单的功能,以实现等同于gluLookAtgluPerspectiveglColor3fvglTranslatefglRotatefglLightfv,... < / LI>
  • 使用glDebugMessageCallbackglDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, &unusedIds, GL_TRUE)
  • 检查上述和每个警告/错误
  • 确保屏幕上的图片与立即模式
  • 相同

我仍然得到类似的结果: VAO 中的三角形数量越多,CPU时间越长(用户系统)我们在glXSwapBuffers内度过。

这一切似乎都非常意外(至少可以说) 当然,一旦启用了 V-Sync ,CPU时间(用户系统)就会下降到~0。

所以看起来在glXSwapBuffers里面我们有一个与要渲染的三角形数量直接相关的主动旋转(渲染的三角形越多,等待一些的CPU循环就越多 event)。