前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >GPU Ray Tracing简述

GPU Ray Tracing简述

作者头像
Peter Lu
发布2019-08-19 11:16:13
1.8K0
发布2019-08-19 11:16:13
举报
文章被收录于专栏:LETLET

之前的《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-Tracing/webgl-GPU-Tracing/tracing.html

目前英伟达也推出了针对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.” 就用这句话作为本篇的结尾吧。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 LET 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档