我想在任意位置写入纹理缓冲区,而不需要上传大量数据来提高性能。我不做glSubBufferData,因为有很多不连续的写,这会导致AMD GPU的显着性能损失。
存储所有新数据的成本也很高。只写入更改的内容可以显著提高性能。
为了实现这一点,我使用了GL_MAP_UNSYNCHRONIZED_BIT,它使我的性能提高了一倍,但我担心我会遇到未定义的行为,尽管我看到了巨大的性能提升(并且一切都正确呈现)。
在下面的伪代码中,我的意图是写入一个纹理缓冲区,它在顶点着色器中使用。
void render()
{
if (frameNumber % 50 == 0) {
ptr = glMapBufferRange(..., GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
randomlyWriteIntoBuffer(ptr);
glUnmapBuffer(...);
}
// do everything else (upload, bind VAO, texture, program, etc)
bindTextureBufferThatWasMappedAbove();
glDrawArrays(...);
frameNumber++;
}
我的代码有以下约束:
- 我只在帧的开始写入Map纹理缓冲区一次,或者从不为该帧写入。
- 我只从缓冲区读取它在着色器通过纹理缓冲区。
- 我不在乎数据是否在绘制调用时被部分践踏。如果在绘制调用发生时存在陈旧和非陈旧数据的混合,则是可接受的,例如一半的缓冲区具有写入的最新Map数据,而另一半是旧的,只要旧数据最终在稍后的帧中与较新数据一起可见,或者一些后续的缓冲区写入覆盖它。
- 我正在写入的备份缓冲区在其他任何地方都没有使用。
我的用户并不都有GL 4.4+,所以我不能使用持久性标志。
如果这是未定义的行为,我如何实现上传?
1条答案
按热度按时间vecaoik11#
OpenGL对非同步贴图的行为非常清楚。具体来说,通过这样做,* 你 * 负责同步:
如果来源或修改缓冲区的挂起操作与Map区域重叠,但此类先前和任何后续操作的结果未定义,则不会生成GL错误。
“未定义”是指 * 未定义 *;没有任何保证如果你没有让CPU等待Map缓冲区,直到从它读取的前一个操作完成,那么OpenGL对接下来发生的事情提供零保证。