找回密码
 立即注册
查看: 828|回复: 15

【图形渲染-引擎】软光栅真的这么强?为何ue5之前的引擎做不到?

[复制链接]
发表于 2021-9-22 07:48 | 显示全部楼层 |阅读模式
(原文链接:https://tellusim.com/compute-raster/?utm_source=com.yinxiang&utm_medium=social&utm_oi=625554198712946688)
又看到老外一个很强的软光栅demo,没做culling的情况,也非常接近ue5 nanite的微几何体渲染。代码并不多,所以,很疑惑,为何现在又重新提起软光栅?以前为何不用??是以前硬件不行还是以前的算法不行??那按道理,unity 要做,也并不难啊,为何unity 也没官宣要做虚拟几何体渲染?











本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2021-9-22 07:50 | 显示全部楼层
并不是。
历史上是先有的光栅化算法,再有的硬件加速。显卡的前身叫图形加速卡,就是因为软件太慢,用硬件固化的方式来加速的。如果软光栅无条件比硬光栅快,恐怕世界上就不会有GPU这个东西了。
在同一代技术同等晶体管数目的前提下,ASIC(专用芯片)永远是比通用ALU(计算逻辑部件)+程序效率高的。这是因为通用的电路需要考虑很多情况,需要支持可编程、调度、分支预测等等,这些都会消耗相当多的硬件资源(晶体管)。而且程序也是数据,放在内存上要读进来,这个延迟很高的。(随随便便就是几百个时钟周期)
这也是为什么谷歌会用FPGA甚至是TPU代替GPGPU进行深度学习方面的计算,因为任何时候针对特定应用固定算法,进行针对性硬件设计,都能大大提高效率。
但是题目所引文章里的数据是基本可信的。UE5的表现大家也有目共睹,这是为什么呢?
原因其实是在于边界条件,也就是特定的应用场景和设计选择上。
首先,正是因为纯硬件的光栅化模块效率很高,到目前为止,在大部分游戏当中现代GPU的性能瓶颈很少出现在光栅化这个环节,加上shader日趋复杂,GPU花在跑shader上的时间越来越多,所以近代GPU在设计的时候,光栅化模块的性能设计都是根据到目前为止的经验,对于典型运用场景“够用”的情况下,尽可能节省。(留出芯片面积给其它,特别是堆flops)
具体来说,无论是N卡还是A卡,相对于庞大的计算核心阵列和RB(渲染后端),光栅化模块在芯片上的面积其实小得可怜。数量也很少,一般就是2个到4个左右。
这是因为当代游戏当中,特别是PBR(基于物理的渲染)流行起来之后,顶点上面附属十几个属性已经家常便饭,ps绑10来张贴图也是屡见不鲜。在这种情况下,就这点光栅化性能就绰绰有余了。
但是题目当中的文章,以及UE5 Nanite的展示,演示的是什么呢?文章当中的软光栅,只是完成了一个对深度缓冲区的输出,也就是类似于阴影贴图的渲染。而UE5到目前为止演示最多的,就是沙石材质的土堆和模型。
并且两者都采用了面数非常高的,不透明的静态模型。因为面数高,所以单个三角形面积很小。
简单来说就是高面数+极少属性+简单材质。
这恰恰是当今GPU硬件光栅化管线所最不擅长的情形。因为这种运用场景,是在当代GPU设计想定范围之外的:它从一开始就没有针对这样的应用场景进行设计优化。
或者说,这其实正是DX10以来,抛弃DX9固定管线,导入更多可编程模块所牺牲的部分。
事实上,如果有稍微了解一下UE5的实现,会知道其第一步构建visibility buffer的时候,用的是几乎不带任何属性(除了位置信息)的几何数据。而在后面,也只是对小三角形使用软光栅化,大三角形依然是采用硬件光栅化。
而且UE5的nanite是完全嵌入到传统管线里面的一个子过程:你可以单独为每个mesh打开关闭nanite。这其实不就是在暗示着什么么。
就如已经有别的回答提到的,即便是题目所引文章当中的场景,把FOV调节一下,让大三角多一些,你就会看到完全不一样的结论。硬件光栅化处理小三角形性能低下的主要原因在于其2x2像素的离散化方式:也就是无论三角形多小,最少它都会离散出4个像素,只不过最后通过mask将其中几个像素标志为无效。但是这些无效像素依然会进入管线的下游,跑完几乎全程。(这就是管线,进了管子,就只能一路跑到出口)
以及,现有硬光栅化模块在离散的同时会处理所有附属在顶点上的属性,并未将几何体的处理单独提取出来。
所以,除了大量小三角形(非常高面数的模型)这种极端情况之外,大部分“通常”的情况,硬件光栅化都是比软件光栅化快的。
但是,在现有GPU管线结构下,硬件光栅化必须通过vs/gs来喂数据。而软件光栅化可以在cs当中直接完成。因为vs/gs工作在顶点/primitive级别,所以无法/很难实现cluster/meshlet甚至是sub-object级别的culling,因此虽然硬件光栅化性能好,但是对于复杂场景实际上是做了很多无谓的工作,离散了很多对画面根本就不会有影响的像素出来。而基于cs的软光栅则天然可以在光栅化之前通过自定义mesh的数据格式实现子对象/子网格级别的高效剔除,从而整体浪费大大减少,最终在性能上胜出。
而mesh shader则是根据cs软光栅的这一优点,同时旨在解决cs无法直接连接硬光栅这一局限推出的,介于cs和gs/primitive shader之间的东西。其单纯的性能同样其实是不及vs/gs的,但是因为可以支持自定义mesh格式,更有效地执行更高级别的剔除,对于复杂场景是有可能胜出的。
总结一下的话,就是并非是软光栅化性能高,而是因为其能够方便地实现更为高效的剔除算法,以及在大量小三角形等特定情况下具有优势。
其实大部分性能优化问题均是如此。除了基础技术的飞跃,在同等条件下的优化一般都是拆东墙补西墙,根据具体应用场景寻求最佳平衡而已。脱离了具体场景论优劣是没有意义的。
UE5的伟大之处,其实和谷歌苹果什么的很多产品很像,并不是创造了什么高深莫测的技术,而是将技术恰到好处地,在正确的时间用正确的方式,展现了出来。
发表于 2021-9-22 07:59 | 显示全部楼层
博客里有给windows的可执行文件,就弄下来跑了一下。
数据应该是没问题的。我的显卡是2060,数据比题主的截图高一点,默认参数启动,Compute Shader光栅化三角形的速度是8.9B/s,其他都6.5B/s左右。
RenderDoc截下来,渲染流程就两个Compute Shader,一个Clear贴图,一个做软光栅,反汇编代码没细读,乍看一眼和文章里给的Shader代码一致。
这例子说明对于特定任务,手写软光栅确实会比内置的光栅化管线快。我不清楚原因,可能是因为内置的光栅化管线做了比光栅化更多的事情。
这个例子其实有点问题。
首先三角形真不大。他的光栅化代码里,一个for循环把三角形包围盒里的所有像素遍历了一遍,极度暴力。要是一个三角形有一个屏幕大,那这代码就是GPU一个线程串行给屏幕上每个像素做光栅化,效率就不是很高。
想验证这一点也很容易,这个程序有个启动参数-fov,把这个参数设小,让三角形在屏幕上的面积大点。还有一个参数,-subdiv,曲面细分程度,把这个参数设小(默认是5,可以设置成3),你就会发现软光栅跑得没其他几个快了。
为了防止你fov设太小,这程序里对fov参数设了个clamp(
我用-fov 0.1 -subdiv 1跑起来时候,显卡发出了刺耳的啸叫,感觉对心脏不是很好。

-fov 0.1 -subdiv 3的话,MultiDrawIndirect是5B/s,软光栅就和三角形在屏幕上的覆盖率相关,大概1-3B/s
多数情况下三角形不会分这么细。
这个输入数据也有进行预处理,划分了Meshlet。这个Meshlet的划分对于访存局部性可能会有些影响,这跟index buffer的分布也有关系,这里应该有很多操作空间。
要想把这东西做到现有的引擎里,首先得判断什么时候用软光栅,这个判断显然是个玄学。
其次要考虑这个算法对于现有渲染流程的改动,要考虑如何兼容现有的渲染特性。
还要考虑对于模型的一些预处理。
工程量显然不小。
油腻蹄之类的引擎需要考虑一般用户的需求,做这个吃力不讨好,因为多数用户用不到这个“优化”。
文章里说不需要各种内置管线……我不赞同。就说Ray tracing,高效的BVH travesel也绝对不像他说的写几个Compute Shader那么容易。在RT Pipeline出来之前,很多离线渲染器都用CUDA或者别的东西实现过GPU光追,现在各个都迁移到Optix了。
发表于 2021-9-22 08:09 | 显示全部楼层
做不到?ZBrush从十多年前开始就是基于CPU的软件光栅化,可以实时处理和渲染巨大的mesh...
证据官网就有:


这还不是基于GPU的呢…
所以,其实优化的非常好的软件光栅化一直非常强...
只是看有没有项目有决心应用在实际产品里面罢了...
消除偏见本来就是非常困难的一件事情,加上软件光栅化需要有非常强的工程落地能力和耐心去优化,能做成的人凤毛菱角很正常

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2021-9-22 08:13 | 显示全部楼层
文礼和Elvic大佬已经说的很明白了。我这里给你一个说法帮助你理解:
为什么CPU已经有Cache,OS也有Page Mapping了,应用还需要做自己的Cache和Pool呢?因为应用层掌握有更多的信息,可以比硬件层的Cache节省更多的计算。对于软件光栅化也是一样。
如果只是做和硬件完全相同的光栅化,那(同价格或者同功耗或者同面积或者同计算能力的)CPU/Compute shader无论如何也做不过GPU上的fixed functional pipeline。但是CPU/Compute Shader可以实现更加复杂的光栅化逻辑,从而节省更多的运算、或者满足特殊的需求。
至于UE5之前的引擎,我记得很久之前就有用软件实现的保守光栅化做遮挡剔除的?
发表于 2021-9-22 08:19 | 显示全部楼层
这篇文章比较的是mesh shader和compute based rasterization的性能差异,这个测试Sample也过于简单说明不了任何问题。CS软光栅只在小三角处理方面由于硬件光栅管线,而实际工程落地的难点在于如何高效的过滤或筛选出小三角形,并交给cs based rasterization,如果没有一个高性能的拣选方案,事实上是无法落地的,Nanite的核心就是为了解决这个问题。
Nanite 的 Cluster LOD 是基于屏幕分辨率的动态划分,与场景几何复杂度无关;而传统 Meshlet 或 Mesh Cluster 的划分是基于 Mesh 模型的静态算法,在离线或非runtime阶段预处理,与场景几何复杂度相关。
另一方面,为了把软光栅与硬光栅结合起来,visibility buffer pipeline 是个最佳方案,Nanite 正是把这一系列问题的解决方案整合在了一起,才使得软光栅发挥了威力。
发表于 2021-9-22 08:19 | 显示全部楼层
刚开始看题主的标题,还以为是用cpu端做光栅化,进来看发现是用CS做光栅化。那么既然GPU上有专门光栅化的硬件单元,为什么要占用通用流处理器来处理光栅化呢?第一种情况就是没办法使用raster engine,比如使用visibility buffer pipeline,就需要自己处理光栅化。另一种情况就是raster engine做的不好,raster engine是硬编码,它的实现目标是满足大部分情况下性能最优,对于某些极端情况下raster engine处理的并不好,比如对于像素占用小于4的三角面片。所以对于软光栅化,并不是引擎层面做不到,而是引擎需不需要使用软光栅化。你提的这个问题其实牵扯了一个比较大的问题就是GPU到底有没有必要再用专用的raster engine来做光栅化了MS已经统一了raster engine之前的渲染流程,那么横在中间的raster engine是不是也可以去掉了,到底是统一好还是使用专用的硬件好,这个不是游戏公司和操作系统公司说的算,要看GPU厂商的态度,从目前GPU的架构演变来说,通用化是大势所趋,因为GPU已经不再只服务渲染了,它希望将自己定位在AI上,而AI的市场要远远大于图形渲染。从硬件成本来说raster engine很有可能会被替换成更多的通用流处理器,这样对AI更友好,对图形渲染可能不是最优解但是也不赖。以后的GPU就是并行的通用处理器,不再是图形显卡了。
发表于 2021-9-22 08:29 | 显示全部楼层
unity 属于天才型引擎,整个引擎思维非常跳跃,完全是天马行空无迹可寻的思维方式。
UE 不是那种天才型的引擎,没有天马星空的思维,但是这个引擎最大的成就,就是把细节做到极致,做到登峰造极的地步,繁琐而又枯燥的细节在UE手中变成了艺术。
发表于 2021-9-22 08:32 | 显示全部楼层
可以去参考一下这个系列的文章:
http://filmicworlds.com/blog/visibility-buffer-rendering-with-material-graphs/具体来说,GPU硬件在计算ddx/ddy时是以2×2像素为单位进行有限差分的。对于三角形边缘上的像素,这就导致硬件需要渲染一些显然不在三角形内的像素以保证差分的正确性。对于小三角形,这甚至可以导致需要渲染4倍的像素。显然对于Nanite的目标(每个三角形覆盖一个像素)来说这样的开销是巨大的。
ddx/ddy在什么时候会用到呢?最频繁的,在计算mipmap/各向异性过滤的时候,就需要ddx/ddy。所以即使是deferred也会受到性能影响。(但是并不清楚如果只渲染depth/visibility有没有这个额外开销——猜测为了硬件实现简单也是有的。)
所以软渲染如何计算ddx/ddy?文章中给的方法是使用解析解。Nanite提供额外的一种方案是在渲染好的buffer中进行差分——在边缘处会有误差但是性能更好。
软光栅的一个大问题是很难保证光栅化操作的原子性——对于硬件光栅,深度测试可以保证即使写入多个buffer,其最终结果也是一致的;但是软光栅不得不依赖于64 bit atomics(Nanite)或者干脆只渲染depth(题目中的文章)。在同时渲染多个buffer时也会遇到一致性以及内存占用的问题。这也是为什么Nanite和之前贴出的文章都使用了visibility buffer而不是deferred。
发表于 2021-9-22 08:41 | 显示全部楼层
这个问题粗看觉得有点标题党,拿了一个很极端的条件下的测试结果推出一个结论
但仔细想了想,这个问题还是很有深度的
光栅化的算法并不算复杂,尤其是题中链接的暴力方案。一些更复杂的算法无非做了一些binning和coarse raster
题目中的demo,以及ue5,都是使用原子操作写visibility,就结果而言,比较高效并且正确,但事实上传统光栅化是需要支持raster order的,在这中间,甚至需要支持depth/stencil状态的切换,而前面的方案不能保证。软光栅如果要保证raster order,应该会需要做很多的同步和排序,性能恐怕就不好看了
这就导致,软光栅的方案适用于的场合是有局限的。不过即便有局限也能在某些场合下代替硬光栅,例如shadowmap,visibility buffer这种
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 16:34 , Processed in 0.153719 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表