新一代图形编程接口Vulkan简介(二)
想免费获取内部独家PPT资料库?观看行业大牛直播?点击加入腾讯游戏学院游戏程序行业精英群
711501594

较低的一条线指的是处理器CPU的使用率,上端的线表示系统CPU的使用率。两条线在Vulkan中都有所下降。
这种高性能的获取来源于Vulkan提供的命令缓冲区的复用机制。对于绘制同样的模型,Vulkan可以预先生成渲染的命令缓冲区。其后每帧需要绘制这种物体时,只需要把预先准备好的命令缓冲区送给GPU的命令队列执行就可以了,这部分开销非常小。而与之对应的OpenGL ES即使是绘制同样的物体,也需要在每帧调用同样的draw call。每次draw call的调用意味着驱动内部需要准备好shader代码,准备顶点数据与vertex shader的绑定,切换纹理数据和状态等等。一旦draw call数量过于巨大,那么GPU其实大多数时间是在等待驱动程序完成draw call的准备工作,而不是与CPU并行运行。
Vulkan提高性能的另一个举措就是可控的错误检查和调试信息输出。对于应用来说只有在开发调试阶段错误检查和调试信息才是有用的,一旦应用被验证后,就不需要这些冗余的操作。Vulkan为应用提供了关闭这些操作的机制,使得CPU开销进一步减少。
OpenGL ES提供了隐式的资源并发访问保护机制,这使得应用开发人员不需要考虑某个资源访问是否会影响到GPU渲染,或者其它线程的访问。例如在GPU渲染管线正在使用纹理时,应用调用glTexSubImage2D去试图更新纹理数据,这个时候驱动会在内部去等待GPU渲染执行完毕之后再更新该纹理,然后返回应用。一切看起来都很完美,但是这给应用程序带来性能的损耗,因为应用需要等待GPU执行而什么都不能做。其次,这给应用的执行时间带来了不可预测性,应用不会知道这次更新纹理什么时候能够完成。Vulkan则直接放弃了这种隐式的保护机制,让应用来负责资源访问的保护。
OpenGL ES的另外一个问题是它对多线程渲染支持不好。这导致主场景的渲染工作通常都压在一个线程上面,导致CPU某个核的负担过重。Vulkan力图改进这种单线程渲染的方式。Vulkan不再限制渲染命令只能在当前线程绑定的context上面生成和执行。反之,它允许多个线程同时为某个场景生成渲染命令。通过把工作分散给数个线程,降低了CPU单核负担,也就变相提升GPU的吞吐量,提升了渲染性能。
需要注意的是Vulkan为了提供这种多线程的渲染能力,大幅度改变了OpenGL ES的context机制。其与OpenGL ES的区别如下:
OpenGL ES有全局的状态,例如alpha blend, depth function等等,而Vulkan把这些状态都保存在Pipeline object中,任何需要的线程都可以使用该object。
OpenGL ES的每个渲染线程需要绑定一个context来负责管理渲染时使用的资源等等。Vulkan则是让资源存在于各自的object中,渲染命令需要使用时直接访问该object。
OpenGL ES的context,状态,渲染资源在多线程访问时都是线程安全的,Vulkan则不保证上述这些object能够安全访问,这需要应用自己去实现保护。
Vulkan与OpenGL ES另外一个不同则是在内存的管理上面。传统的OpenGL ES需要驱动自己负责为渲染资源,FBO等分配内存并且管理。那么应用是无法知道驱动内部到底使用了多少内存,也无法知道资源什么时候不被驱动和GPU使用可以释放掉了。经常会出现应用维护一份资源同时OpenGL ES驱动又维护一份资源的情况。这在移动平台上面会加重本来就不宽裕的内存开销。Vulkan自己不会维护这部分内存,而是把分配管理的权利交给了应用,使得应用可以统一的优化内存开销。