之前的《Ray Tracing简述》,我们介绍了光线追踪的基本概念。当我们实现了CPU版本的光线追踪时,我们自然会有一个念头,是否能够提供GPU版本的光线追踪。在这个过程中,主要分为三个步骤:可行性分型,性能瓶颈分析以及Ray Tracing的可编程渲染管线。
在OpenGL GLSL正式版还没有推出时,研究人员就着手尝试,是否可以借助可编程渲染管线的流程实现Ray Tracing,这样,借助GPU的并行能力,提升Ray Tracing的渲染效率。
如上图,左侧是可编程渲染管线的基本流程,右侧是Ray Tracing的简化流程。简单说,我们的第一步就是试图用左侧的流程来实现右侧的逻辑。强调一下,那是一个还没有GPGPU概念的年代,那个年代的shader对一些数学函数还不支持,比如sin,片元中还不支持条件语句。
最终采用multi-pass的思路,实现了两者之间的过渡。如上图,创建一个FBO,累加形成最终的图像效果,在GPU内存中创建所需要的纹理,保存过程中所需要的变量以及所需的数学函数映射值等,使用stencil buffer实现条件判断,这样,如上的六张图片,对应六个Pass,最终累加完成渲染。当然,这里我们只使用了片元着色器。同理,在图1的Ray Tracing中,对应4个Pass,每一条Ray都有一个状态state,对应需要执行的Pass:Traverse,intersecting,shading和done。这样,我们只需要渲染一个和屏幕像素大小相等的矩形,采用基于state的stencil buffer来执行对应的Pass并修改对应的state。下图是不同场景对应的Pass个数以及每个Pass中active的thread比率。
这样,研究人员证明了,即使是为rasterization设计的渲染管线,也可以实现Ray Tracing,同时在判断射线和场景相交上,GPU的性能更为出色,当然,希望片元中支持条件语句。
可行性只是第一步,GPU的性能才是关键。这时,作为程序员,遇到性能瓶颈的第一准则是什么?当然是嘲讽你的显卡太差了,升级一下呗。摩尔定律是神奇的,CPU的免费午餐结束了,GPU的才刚刚开始。然而,英伟达说“这个锅我不背”。英伟达的研究人员写了一篇论文,专门研究了当时RayTracing在GPU中的瓶颈是什么?
比如,如上的一个简单改动,将while改为if,就会带来如下的性能提升。至于while和if的区别在于前者尽可能晚的退出(需要判断N次),而后者尽可能早的退出(只判断一次),假设有两条射线,他们在while下判断完全一致的可能性远远小于if,因此diversity的现象会更严重,如下可见,GPU的利用率从53%提高到70%。
论文中还介绍了其他方法,比如在if的基础上采用Persistent的方式等,我们不再此详细介绍。总之,这篇论文让人们意识到, Ray Tracing性能优化的瓶颈不是想象中的GPU内存,寄存器等硬件资源的不够,而是GPU diversity现象严重,换句话说,Thread中大部分并没有工作,并没有充分利用GPU的并行。
想想也不难理解,GPU是基于rasterization的逻辑而形成的渲染管线,而multi-pass的思路只能算是移植了Ray Tracing的逻辑,因为diversity而导致无法发挥GPU的优势,也算是意料之中。于是,开始了探索适合Ray Tracing的高效的渲染管线。
英伟达推出了第一个基于GPU的通用的raytracing引擎,大概架构如上图,黄色部分需要用户自定义实现,而蓝色部分,主要是Ray-Object的Intersection部分则由OptiX实现。另外,整个逻辑层也由OptiX负责。
OptiX具有不错的通用性,用户可以根据自己的材质特点自定义自己的渲染模块,为RayTracing的渲染管线提供了一个可供参考的架构。至于有什么缺点,我并没有用过其SDK,咱也不敢批评英伟达,所以只要原封不动的引用论文的描述:OptiX最终会把所有的模块合并成一个,最终还是一个megakernel,用户基于材质做优化,比如每一个thread对应的材质都不同,在这种极端情况下GPU无法并行。下面是个人的理解:OptiX并没有根据材质打包,将材质相同的放在同一个warp下,只是对Traverse进行了优化,而Shading并没有优化,因此diversity并没有彻底解决。
于是,在OptiX的基础上,有人又提出了称为Wavefront的架构,从logic自下而上,每次执行完任务后,会给下面的模块分发新的任务,形成一个个的Queue,然后每个模块就针对Queue中的数据进行对应的操作。这样,Queue中的任务基本相同,充分利用GPU的并发特性。
Wavefront在实现上略有复杂,基于computer shader,个人开发了一个C++的版本,然后移植到WebGL中,目前Chrome Canary也支持Computer Shader,有兴趣的可以看看WebGL下的效果,链接如下:https://pasu.github.io/GPU-Tr...
目前英伟达也推出了针对Ray Tracing的显卡RTX,可能在光线追踪的技术上,会有很大的变化,这块我并没有了解,就不讨论了。另外,刚才主要是在设计或架构的层面讨论Ray Tracing的渲染管线,具体到细节,比如场景的Primitives是采用voxel或者k-D tree还是BVH,以及在GPU中如何解决递归和堆栈开销,并行查找性能的优化,这些也有很多可以深入交流的部分,而在shading中,材质对渲染效果的影响也是巨大的,不同的材质属性之间如何叠加,形成逼真的视觉效果,也是一门学问。
记得上学年,在Advanced Graphics开课前,有学生问是否会讲Rasterization,老师的回复是“Sorry, we do not talk about rasterization because Ray Tracing is the future.” 就用这句话作为本篇的结尾吧。
作者:Peter6
原文链接:https://mp.weixin.qq.com/s/JnFLio\_1kmw\_kfO9xyda3w
微信公众号:
推荐阅读
更多IC设计技术干货请关注IC设计技术专栏。