opengl 对整个缓冲区使用GL_MAP_UNSYNCHRONIZED_BIT glMapBufferRange及其安全性

2ic8powd  于 2023-10-18  发布在  其他
关注(0)|答案(1)|浏览(111)

我想在任意位置写入纹理缓冲区,而不需要上传大量数据来提高性能。我不做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+,所以我不能使用持久性标志。
如果这是未定义的行为,我如何实现上传?

vecaoik1

vecaoik11#

OpenGL对非同步贴图的行为非常清楚。具体来说,通过这样做,* 你 * 负责同步:
如果来源或修改缓冲区的挂起操作与Map区域重叠,但此类先前和任何后续操作的结果未定义,则不会生成GL错误。
“未定义”是指 * 未定义 *;没有任何保证如果你没有让CPU等待Map缓冲区,直到从它读取的前一个操作完成,那么OpenGL对接下来发生的事情提供零保证。

相关问题