将多个对象异步上传到 GPU
Uploading multiple objects to GPU asynchronously
我有一堆来自好奇号火星车立体相机的3D模型,在火星上行驶。模型正在从磁盘异步加载多个模型。现在我需要将这堆模型异步上传到 GPU(在运行时),以防止渲染循环中出现停滞,这种情况正在发生。
现在上传模型的方式:
glGenVertexArrays(1, &_vaoID);
glGenBuffers(1, &_vbo);
glGenBuffers(1, &_ibo);
glBindVertexArray(_vaoID);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, _vertices.size() * sizeof(Vertex), _vertices.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<const GLvoid*>(offsetof(Vertex, location)));
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<const GLvoid*>(offsetof(Vertex, tex)));
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<const GLvoid*>(offsetof(Vertex, normal)));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices.size() * sizeof(int), _indices.data(), GL_STATIC_DRAW);
glBindVertexArray(0);
以及它的渲染方式:
glBindVertexArray(_vaoID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
glDrawElements(_mode, static_cast<GLsizei>(_indices.size()), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
现在,我每次在渲染循环中都会将大约 20 个模型上传到 GPU(当有模型从磁盘加载并准备上传到 GPU 时),而且很多时候,应用程序会停滞大约 50-400 毫秒,具体取决于模型的顶点/法线/索引的数量。
VBO 之间的乒乓球(更新一个,从一个读取)在当前管道中可能不起作用,因为每个模型都有随机数量的顶点/法线/索引,并且需要连接到一个特定的纹理。
我正在寻找任何提高性能的解决方案。
编辑 1
我现在已经成功地创建了指向我的 VBO 和 IBO 的指针,但是我很困惑当缓冲区返回到主线程时,我应该如何取消映射缓冲区。我的第一个想法是像这样分别取消映射 VBO 和 IBO: `
for (int i = 0; i < _vertices.size(); i++) {
_vertexBufferData[i] = _vertices.at(i);
}
glUnmapBuffer(GL_ARRAY_BUFFER);
for (int k = 0; k < _indices.size(); k++) {
_indexBufferData[k] = _indices.at(k);
}
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
但是我收到一个错误,说缓冲区已经未绑定或未映射。我只需要执行第一次取消映射吗?
您描述的问题称为缓冲区对象流。
简而言之,假设您有一个触发器,必须加载特定模型。然后:
- 按照您的描述创建 VAO 和 VCO,但尚未加载任何数据。为此,您可以使用
glBufferStorage
。 - 将缓冲区映射到内存中,并启动一个线程以用数据填充该缓冲区。线程将执行所有耗时的磁盘 I/O 和填充映射的内存区域。
- 工作线程完成后,通知主线程。
- 在主线程中,收到通知后,取消映射缓冲区并将 VAO 标记为已加载以进行后续渲染。
显然,在 1 到 4 之间,您的主线程会像往常一样继续渲染,而不会渲染该挂起的 VAO。
相关文章:
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 在使用GPU支持编译Tensorflow时,会遇到CUDA_TOOLKIT_PATH未绑定变量
- 有没有办法简单地从 GPU 调用多个 cpp 输出文件?
- 如何在C++中实现带有packaged_task的异步等待循环?
- 创建 Spdlog 异步文件记录器时遇到困难
- C ++异步键盘输入(标准方式)
- 在 DirectX 11 中从 GPU 读回顶点缓冲区(并获取顶点)
- 跨平台 GPU 计算
- C++:从GPU内存(cudaMemcpy2D)获取BGR图像(cv::Mat)
- 请求最简单的 OpenMP 目标 GPU 示例
- 在 gtkmm 中异步加载图像
- 带有 Boost.Beast 的异步读取标头
- 如何在 c++ 中异步调用静态方法?
- libcurl :C++处理多个异步请求
- 如何在C++上启动异步线程
- TCP 服务器的异步读取使用 boost::asio 打印客户端套接字发送的数据
- DirectX 11 如何处理来自 GPU 上的 sharedHandle 的图像
- 增强 ASIO 和串行端口异步读取
- 将多个对象异步上传到 GPU
- 在我的CUDA运行时间计划中,CPU和GPU可以异步计算,但不能合作地计算