【问题标题】:How do I grow a buffer OpenGL?如何增长缓冲区 OpenGL?
【发布时间】:2015-01-03 10:34:30
【问题描述】:

是否可以在 OpenGL 中增加缓冲区?

假设我想使用实例化渲染。每次在世界上产生一个新对象时,我都必须使用实例数据更新缓冲区。

在这种情况下,我有一个 3 个浮点数的缓冲区

  std::vector<GLfloat> offsets = {0.0f,0.5f,1.0f};
  auto offset_buffer = buffer::makeBuffer(BufferDraw::STATIC_DRAW, offsets);

如果我想要 4 个元素怎么办?我必须用更大的尺寸调用 glBufferData 吗?但是旧数据会发生什么,它会被复制吗?还是我必须完全删除缓冲区并创建一个新缓冲区?

【问题讨论】:

  • 有一个扩展可以做到这一点,否则你需要分配新的缓冲区并复制数据并填写新的。否则旧数据会丢失
  • 我可以直接从 OpenGL 复制数据,还是必须再次将数据从我的 ram 发送到 vram?
  • @ratchetfreak:那是哪个扩展名?我唯一想到的是GL_ARB_sparse_buffer。您可以保留比您需要的更大的缓冲区,然后在填充缓冲区时提交内存页面,但扩展所需的最小页面大小为 64 KiB,浮点数仅为 4 个字节;)

标签: opengl


【解决方案1】:

你绝对不能用新的尺寸打电话给glBufferData (...) 来做这件事。这将孤立旧缓冲区并为您提供一个具有更大存储空间的新缓冲区(其内容与先前分配的内存无关)。

只要之前任何需要它的 OpenGL 命令仍在管道中排队,旧数据就会继续存在。在这些命令完成后,OpenGL 允许回收内存 - 您不必担心泄漏,但就地增长不会自动发生。

GL 3.1 引入了复制缓冲区的概念,这将帮助您更有效地执行此操作。

考虑以下伪代码:

// Bind the old buffer to `GL_COPY_READ_BUFFER`
glBindBuffer (GL_COPY_READ_BUFFER, old_buffer);

// Allocate data for a new buffer
glGenBuffers (1, &new_buffer);
glBindBuffer (GL_COPY_WRITE_BUFFER, new_buffer);
glBufferData (GL_COPY_WRITE_BUFFER, ...);

// Copy `old_buffer_size`-bytes of data from `GL_COPY_READ_BUFFER`
//   to `GL_COPY_WRITE_BUFFER` beginning at 0.
glCopyBufferSubData (GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, old_buffer_size);

在实际情况下,您可以将缓冲区数据从任何绑定位置复制到任何其他绑定位置。新的GL_COPY_..._BUFFER 绑定点很方便,但不是必需的,因为它们不会干扰任何其他绑定。

【讨论】:

  • 复制数据后是否可以将new_buffer的句柄改为old_buffer的句柄?否则我将不得不创建一个新的 vao。
  • @MaikKlein:嗯,您可以随时在old_buffer 上调用glBufferData (...) 将其复制到new_buffer,然后将数据复制回来。在调整原始缓冲区大小时,您实际上可以使用“new_buffer”作为备份,而不会使存储在 VAO 中的顶点指针失效。当然,如果可以通过过度分配已知大小会增长的缓冲区来避免小幅增量增长(与制作多个副本相关的驱动程序开销相比,少量浪费的内存通常更可取),那么您当然应该避免这种增长。
  • @MaikKlein 如果您预先生成 old_buffer 和 new_buffer,您可以孤立旧缓冲区和 swap(old_buffer, new_buffer);
猜你喜欢
  • 2010-12-18
  • 2016-07-20
  • 2017-06-14
  • 2014-06-26
  • 1970-01-01
  • 1970-01-01
  • 2013-05-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多