更新图形设备中的内存区域(纹理,缓冲区等)与更改渲染状态并不完全相同。
使渲染状态更改昂贵的原因是驱动程序必须执行的工作量才能验证新状态并重新排序管道。这很可能还会在CPU和图形设备之间引起一些同步。但是,设备之间传输的数据量对于状态更改应该很小(可能只有几个命令)。
另一方面,对于纹理/缓冲区更新,主要成本在于数据传输本身。从理论上讲,除非您在更新后将纹理数据读回CPU,否则不应有同步或流水线停滞。但是,应该考虑另一方面:API开销。即使您要发送到图形设备的数据量很小,但如果这样做足够频繁,最终与驱动程序/设备进行通信的成本将变得比数据传输的成本更高。这就是为什么在优化渲染器时批处理如此重要的另一个原因。
因此,在您看来,最好的方法是在新数据到达时,保留要更新的纹理的系统内存副本。设置一个脏标志,并glTexSubImage
针对整个纹理(或其较大的顺序部分)将尽可能多的更新合并为一个。您也可以使用Pixel Buffer Objects并尝试执行异步数据传输,以尽可能减少流水线停顿。如果可以实现某种形式的双缓冲,则可以在渲染纹理的一个副本时对其进行写入。本教程探索这种情况。这是我的直观方法,我将尝试减少API调用的次数并“分批”纹理更新。话虽这么说,这是非常投机的,您必须将其与其他方法(例如进行几次小的更新)进行比较并将其进行比较,以确保确定哪种情况最适合您的使用情况。
附带说明一下,NVidia的本次演讲也很有意义,并且提供了很多很好的见解:在OpenGL中实现零驱动程序开销。