Zho*_*Hua 2 c++ opengl performance glm-math
我试图渲染一个点云(> 1 亿点),我将所有数据传输到 GPU 并仅使用缓冲区名称来访问它。一切正常,直到我实现了一项要求我将所有数据传输回 RAM 的功能。
这就是我将数据传递给 GPU 的方式:
glBindVertexArray(vao);
// some data
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * GetSize() * 3, &vertices[0], GL_STATIC_DRAW); // pos
// some attributes
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); // pos
...
// some other code
...
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glDisableVertexAttribArray(0);
// Clear the contents in the RAM
vertices.clear();
vertices.shrink_to_fit();
Run Code Online (Sandbox Code Playgroud)
然后,我需要一个函数来恢复数据以保存更改,这就是我所做的:
// restore data back to RAM
// this code was called for >4000 times
glBindBuffer(GL_ARRAY_BUFFER, c.vbo);
c.vertices.clear();
c.vertices.resize(c.sizeg);
glGetBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(glm::vec3) * c.sizeg, &c.vertices[0].position.x);
Run Code Online (Sandbox Code Playgroud)
之后,每次我需要渲染点云时,程序都会挂起。
我删除了所有其他代码以仅测试此代码,而这段数据传输代码正是导致延迟的原因
感觉每次我尝试渲染导致它挂起的数据时,GPU 内部都有大量的数据副本。但是,当我将数据从GPU回传到RAM后,原本在GPU内部的数据没有受到影响,我认为渲染应该和以前一样流畅,但事实并非如此。
导致这种滞后的 OpenGL 状态是否发生了变化?
您向 OpenGL 做出了承诺。然后你违背了你的诺言。所以OpenGL因此惩罚了你。
你告诉 OpenGL你将如何使用这个缓冲区对象:
Run Code Online (Sandbox Code Playgroud)GL_STATIC_DRAW
这意味着您告诉 OpenGL 您将写入缓冲区 ( DRAW) 但不从中读取。你说你很少写信给它(STATIC)。因此,OpenGL 实现尽职尽责地将缓冲区对象的存储放在最适合 GPU 访问的位置,但不适用于 CPU 访问。
然后你从中阅读。你做了你答应OpenGL你不会做的事情。
现在,人们(很多人)一直在打破对 OpenGL 实现的这些承诺。如此多的实现基本上不再相信它们。也就是说,他们不会听你说你要对缓冲区做什么,而是关注你实际做了什么。
实现看到您从缓冲区读取。所以它假设你打算有规律地这样做。因此,它现在将缓冲区的存储传输到更适合 CPU 读取的位置……但不太适合GPU 读取。
现代 OpenGL 有一个缓冲区对象创建 API,其中不再允许说谎。您指定可以在缓冲区上使用哪些操作,OpenGL 实现将通过使所有其他访问失败来阻止您这样做。
如果使用缓冲存储API,那么它很可能是试图从缓冲区读取glGetBufferSubData会不会导致API只是洗牌周围的内存。防止存储改组是这个 API 的一半。如果您仍然从您的实现中获得这种减慢效果,那么您可能无法在 OpenGL 中阻止它。
最有效的替代方法(除了使用 Vulkan 可以完全控制内存)是根本不尝试从 OpenGL 读取它。也就是说,不要将 GPU 存储视为可以在需要某些数据时回读的内容。如果您需要使用 CPU 上的数据,请将其保留在那里。也就是说,在 CPU 内存中也保留一份它的副本。
| 归档时间: |
|
| 查看次数: |
76 次 |
| 最近记录: |