glMapBufferRange 持久缓冲区和交错数据

glMapBufferRange persistent buffers and interleaved data

本文关键字:数据 缓冲区 glMapBufferRange      更新时间:2023-10-16

好吧,经过更长的休息,我在这里有点茫然。 我正在尝试使用持久映射的缓冲区,拆分为 2 个缓冲区以提高性能。如果将其用作一个缓冲区,一切正常,一旦将其用作 2,它就会惨败。我不确定我错过了什么,但也许有人可以启发我。我阅读了很多教程和描述,但到目前为止,没有运气更好地理解它或找到这些问题的答案。

对于我的设置,我有以下数据:

Buffer[0] = Point.X;
Buffer[1] = Point.Y;
Buffer[2] = Point.Z;
Buffer[3] = U;
Buffer[4] = V;
Buffer[5] = Color.X;
Buffer[6] = Color.Y;
Buffer[7] = Color.Z;
Buffer[8] = Color.W;

在我的没有持久缓冲区的方法中,我这样做:

...
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * TotalSize, Buffer, GL_STREAM_DRAW);
...
glVertexAttribPointer(VERTEX_COORD_ATTRIB, 3, GL_FLOAT, GL_FALSE, StrideSize, 0);
glVertexAttribPointer(TEXTURE_COORD_ATTRIB, 2, GL_FLOAT, GL_FALSE, StrideSize, (void*)VertFloatSize);
glVertexAttribPointer(COLOR_ATTRIB, 4, GL_FLOAT, GL_FALSE, StrideSize, (void*)(VertFloatSize+TexFloatSize)); 
...
glDrawArrays(Mode, 0, (BufferData.VertSize / FloatsPerVertex));
...

现在到持久性部分(我在这里省略了栅栏和同步内容,因为这似乎不是问题。

GLbitfield PersistentBufferFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
GLsizeiptr BufferSize=(2 * BUFFER_SIZE);
glBindBuffer(GL_ARRAY_BUFFER, PMB);
glBufferStorage(GL_ARRAY_BUFFER, BufferSize, 0, PersistentBufferFlags);
Buffer = (float*)glMapBufferRange(GL_ARRAY_BUFFER, 0, BufferSize, PersistentBufferFlags);

现在这已经是我的第一个问题 - 这是正确的方法吗?用一个映射它并使用第一个缓冲区运行大小的偏移量继续,然后从那里继续使用第二个缓冲区的数据,或者它应该是像这样的相同存储的 2 个映射?:

glBindBuffer(GL_ARRAY_BUFFER, PMB);
glBufferStorage(GL_ARRAY_BUFFER, BufferSize, 0, PersistentBufferFlags);
Buffer[0] = (float*)glMapBufferRange(GL_ARRAY_BUFFER, 0, BUFFER_SIZE, PersistentBufferFlags)
Buffer[1] = (float*)glMapBufferRange(GL_ARRAY_BUFFER, BUFFER_SIZE, BUFFER_SIZE, PersistentBufferFlags)

我没有发现任何提示,什么是首选的,什么是对的,甚至是错的。如何正确拆分?

然后尝试画画

glDrawArrays(Mode, 0, (BufferData.VertSize / FloatsPerVertex)); //Draw "first" buffer, everything works if only this one.
...next round...
glDrawArrays(Mode, offset_of_datasize_first_buffer, (BufferData.VertSize / FloatsPerVertex)); //Second part of the buffer, fails.

这里不完全确定第二个参数,我发现它的解释令人困惑:

指定已启用数组中的起始索引。

我是否正确,这应该是第二次运行中第一个缓冲区的偏移大小?

除此之外,我使用与上面相同的设置,只是没有glBufferData。 所以无论如何,无论我使用上面的哪个版本,如果我只将其用作 1 缓冲区,它都可以工作,但如果将其用作 2,它看起来就像忽略了缓冲区第二部分的数据。 所以这是我的下一个问题 - 甚至允许使用这样的持久缓冲区吗?它是否尊重使用 glVertexAttribPointer 完成的交错设置,还是仅对顶点和仅对顶点进行简单设置?

如果您需要更多信息或不清楚,请告诉我。非常感谢。

glDrawArrays()的第二个参数不是偏移量,而是第一个顶点的索引,就像使用带有glDrawElements()的索引渲染一样。使用offset_in_bytes/stride_in_bytes获取正确的值,或者实际计算具有步幅函数BUFFER_SIZE并将该值用于glDrawArrays()

第二个参数几乎肯定会给你带来麻烦。offset_of_datasize_first_buffer是索引偏移量还是字节偏移量? 试试offset_of_datasize_first_buffer / FloatsPerVertex.

此外,还可以重新绑定属性指针,并将BUFFER_SIZE添加到最后一个参数,以在第二个缓冲区的开头设置0索引。

在尝试切换属性指针之前,请尝试先确保offset_of_datasize_first_buffer是索引类型而不是字节偏移量。 那应该更快。