OpenGL:强制驱动程序将VBO保留在视频内存中

OpenGL:强制驱动程序将VBO保留在视频内存中,opengl,driver,nvidia,vbo,Opengl,Driver,Nvidia,Vbo,我用GL_DYNAMIC_DRAW指定了一个大型VBO和相应的索引缓冲区。在每个帧中,我通过以下方式对顶点和索引的一小部分进行更改(每个帧中的顶点和索引不同,但与总缓冲区大小相比只有少数): -计算两个缓冲区的最小和最大变化指数 -使用glMapBufferRange映射这些最小-最大范围,并指定GL|u MAP_WRITE|u位| GL|u MAP_FLUSH|u EXPLICIT|u位| GL|u MAP_unsynchronized|u位 -将更改写入映射范围的几个子区域 -为每个更改的子

我用GL_DYNAMIC_DRAW指定了一个大型VBO和相应的索引缓冲区。在每个帧中,我通过以下方式对顶点和索引的一小部分进行更改(每个帧中的顶点和索引不同,但与总缓冲区大小相比只有少数):

-计算两个缓冲区的最小和最大变化指数

-使用glMapBufferRange映射这些最小-最大范围,并指定GL|u MAP_WRITE|u位| GL|u MAP_FLUSH|u EXPLICIT|u位| GL|u MAP_unsynchronized|u位

-将更改写入映射范围的几个子区域

-为每个更改的子区域调用glFushMappedBufferRange

-呼叫glUnmapBuffer

-渲染

我的问题是,驱动程序最初(正确地)在视频内存上分配缓冲区,但当我映射缓冲区时,它在系统堆上重新分配(整个)缓冲区,并在视频上释放缓冲区,然后直接从系统内存渲染缓冲区(我通过glDebugMessageCallback看到这一点)。这成为我的渲染中的瓶颈(PCIe速度很快,但直接从视频内存渲染同一缓冲区的速度大约是前者的两倍)

是否有办法强制驱动程序将缓冲区保留在视频内存中,只将请求的范围映射到主机内存中,并将指示的子区域刷新回设备内存?
我在windows和NVIDIA卡上

您可以使用glBufferSubData(…)直接修改视频内存中的缓冲区数据。此函数允许您更改缓冲区的一个子集(或整个缓冲区)BufferSubData不会更改驱动程序保存vbo数据的位置,实际上比缓冲区映射慢,因为它需要额外的数据copy@user1282931:您始终需要额外的数据副本。即使将VBO映射到进程地址空间,最终也可能会得到一个额外的副本。使用同步命令直接写入PCI地址空间会导致各种各样的问题(本质上它会迫使CPU与I/O操作同步)。使用像
glBufferSubData
write
这样的命令,可以让操作系统和驱动程序在调度操作时有更大的回旋余地,从而提高性能。特定于Linux,但适用于其他OSs我建议阅读以下内容:@datenwolf:您总是需要一个数据副本是正确的,但glBufferSubData还需要一个。使用glBufferSubData,您首先将值计算到客户机分配的cpu内存中,然后将值传递给glBufferSubData,glBufferSubData将值复制到驱动程序分配的固定cpu内存中(因为在其他情况下需要同步),然后DMA将其传输到GPU。使用glMapBufferRange,您可以直接将值计算到驱动程序分配的固定cpu内存中。glMapBufferRange不执行您刚才描述的操作。您可以使用glBufferSubData(…)直接在视频内存中修改缓冲区数据。此函数允许您更改缓冲区的一个子集(或整个缓冲区)BufferSubData不会更改驱动程序保存vbo数据的位置,实际上比缓冲区映射慢,因为它需要额外的数据copy@user1282931:您始终需要额外的数据副本。即使将VBO映射到进程地址空间,最终也可能会得到一个额外的副本。使用同步命令直接写入PCI地址空间会导致各种各样的问题(本质上它会迫使CPU与I/O操作同步)。使用像
glBufferSubData
write
这样的命令,可以让操作系统和驱动程序在调度操作时有更大的回旋余地,从而提高性能。特定于Linux,但适用于其他OSs我建议阅读以下内容:@datenwolf:您总是需要一个数据副本是正确的,但glBufferSubData还需要一个。使用glBufferSubData,您首先将值计算到客户机分配的cpu内存中,然后将值传递给glBufferSubData,glBufferSubData将值复制到驱动程序分配的固定cpu内存中(因为在其他情况下需要同步),然后DMA将其传输到GPU。使用glMapBufferRange,您可以直接将值计算到驱动程序分配的固定cpu内存中。glMapBufferRange不执行您刚才描述的操作。