WebGPU性能测试分析
大家好,本文对WebGPU进行性能测试和分析,目的是为了对比WebGL和WebGPU在“渲染”和“计算”两个维度的性能差异,具体表现为CPU性能和FPS性能两个方面的性能数据差异。
我们会分别在苹果笔记本和配备RTX显卡的台式机上,对WebGL和WebGPU分别进行性能测试。
本文对于WebGPU使用了“reuse render command buffer”和“dynamic uniform buffer offset”两种优化,相关介绍可以参考WebGPU学习(十一):学习两个优化:“reuse render command buffer”和“dynamic uniform buffer offset”。
本文只使用了WebGPU的基础能力,还没有使用更高级的特性(如draw indirect、多线程渲染等),所以理论上WebGPU相比WebGL的性能优势还可以进一步地扩大。
测试的代码
测试的代码在Github上
测试结论
这里先给出最后的测试结论:
- 在“渲染”性能上,WebGPU比WebGL快3倍以上
- 在“计算”性能上,WebGPU比WebGL快50倍以上
测试环境
设备一:13“MacBook M1 Pro
操作系统:Mac OS Big Sur
设备二:配备RTX显卡的台式机(i7-4790+ RTX 2060 Super)
操作系统:Win10 64位
WebGL运行的浏览器:Chrome(版本 91.0.4472.114(正式版本))
WebGPU运行的浏览器:Chrome Canary(v93.0)
测试“渲染”的性能
场景描述
该场景的设计思路为:
在固定分辨率的屏幕当中,用WebGL和WebGPU去渲染相同个数的固定大小的三角形,三角形个数从小到大进行递增,三角形颜色都为随机的灰度颜色;
每一帧提交对应三角形个数的DrawCall进行重绘(一个三角形对应一次DrawCall)(这里的每个三角形可看为场景中的一个物体。实际场景中的物体通常由几百上千个三角形组成,但是此处为了简化和突出性能测试的重点,所以一个物体只由一个三角形组成)。
为了能更好的体现重绘的效果,我们在距离+Z轴方向(指向屏幕的方向)的最近的1000个三角形中,随机选取了100个,进行Z轴方向的移动,表现效果为三角形的闪烁。这也符合实际的渲染场景中的情况:大部分物体并不是在每一帧都进行数据改变,只有部分会发生数据变化(这个场景中体现为三角形在Z轴方向的位置移动)。
具体的场景效果如下图:
结果分析
1)硬件环境为13”MacBook M1:
- 影响CPU性能的因素: CPU传递DrawCall时间
- WebGL:5000个DrawCall命令以内时,CPU在10ms以内可以将其全部发送给GPU进行绘制。可以看出CPU并没有进行等待,原因是GPU在绘制5000个DrawCall命令以内时,完成速度很高,并不需要CPU等待。但是超过5000个DrawCall命令时,CPU的耗时明显增加,而且成线性增长。原因是,在WebGL下,每一个DrawCall命令都必须由CPU传递给GPU进行绘制执行,一旦GPU绘制无法在相应时间内完成,就会要求CPU等待。GPU完成绘制所需时间越长,CPU等待时间就越长,所以造成超过5000个DrawCall命令时,CPU的耗时等待时间线性增加。
- WebGPU:在测试范围内,CPU耗时几乎保持不变。原因是WebGPU标准定义了绘制缓存机制(GPURenderBundle),只需在初始化时提交一次进行缓存,后面就不需要再由CPU发送DrawCall绘制命令给GPU,而是GPU直接在缓存中读取绘制命令并进行绘制。因此可以看出WebGPU通过绘制缓存机制,巨大地释放了CPU线程的运算负担,极大地提高了性能。
- 影响FPS性能的因素:CPU传递DrawCall时间+GPU时间
-
WebGL:5000个DrawCall命令以内,可以保持在60FPS的状态。但是当DrawCall超过5000时,性能成反比例函数曲线下降。因为当CPU发送DrawCall给GPU,时间成线性升高时,FPS的时间被此线性时间影响且成倒数关系。当超过一定的DrawCal数量时,甚至出现了测试崩溃(大于72000个DrawCall)。
-
WebGPU:由于缓存机制,极大的减少了影响FPS最大的权重时间,即“CPU传递DrawCall时间”。因此可以在相对大量的DrawCall发送测试下,保持在较高的60FPS状态。但是当测试达到74000个DrawCall时,也会出现FPS下降,这是因为硬件的GPU已经无法满足运算绘制的要求。
-
2)硬件环境为台式机i7-4790 + RTX 2060 Super
- 影响CPU性能的因素 CPU传递DrawCall时间
- WebGL:1000个DrawCall命令以内,CPU全部发送给GPU进行绘制时,可以看出CPU并没有进行等待,耗时都控制在10ms以内。然后超过1000个以后, CPU的耗时明显增加,而且成线性增长。其整体趋势和M1环境下对比分析相同。但是由于M1环境的CPU性能更好,所以M1在5000以后才表现出CPU耗时线性增加,而台式机在1000的时候已经开始表现出CPU耗时线性增加了。
- WebGPU:在测试范围内,CPU耗时几乎保持不变。原因与M1环境下的原因相同。因此无论是在M1环境还是在台式机环境,由于缓存机制,可以看出WebGPU,都可以大量的释放了CPU线程的运算负担,进而提高性能。
- 影响FPS性能的因素:CPU传递DrawCall时间+GPU时间
- WebGL:30000个DrawCall命令以内,可以保持在60FPS的状态,而M1只能在5000以内,才可以维持60FPS状态,可以看出台式机的RTX显卡明显好于M1的显卡。但是当DrawCall超过30000时,性能成反比例函数曲线下降。原因与M1环境下的原因相同
- WebGPU:其整体趋势和M1环境下对比分析相同。当测试达到82000个DrawCall时,也会出现FPS下降,这是因为硬件的RTX显卡也已经无法满足运算绘制的要求。
测试结论
在当前渲染场景的测试中得出如下结论:
- 由于WebGPU采用了缓存机制,可以避免CPU发送DrawCall指令所带来的等待时间消耗,显著提升CPU的工作效率。相比较WebGL,WebGPU在M1配置下渲染性能提升3倍,台式机i7-4790 + RTX 2060 Super配置下渲染性能提升15倍。
- 如果不使用WebGPU的缓存机制,那么WebGPU的渲染性能只比WebGL快3%左右,两者相差不大。这是为什么呢?这是因为对于WebGPU和WebGL,在GPU端都是通过光栅化管线来渲染,所以两者在GPU时间上都是一样的,不一样的点就在于CPU传递DrawCall时间。然而如果WebGPU不使用缓存机制,那么WebGPU与WebGL一样,每帧都需要在CPU端发送每个DrawCall指令,所以导致两者在CPU传递DrawCall时间上也几乎一样。
- CPU性能对比中,WebGL下,M1配置的CPU耗时参数优于台式机的CPU耗时参数,因此台式机CPU(i7-4790)性能表现不如M1芯片性能。但是在FPS性能对比中,WebGL下台式机的RTX显卡性能明显优与M1芯片。但是不论硬件配置如何,CPU性能的表现和FPS性能的表现,在WebGL下和WebGPU下,整体变化趋势一致。WebGPU性能整体明显优与WebGL性能。
分析Babylonjs关于WebGPU和WebGL的渲染性能对比的Demo
从From WebGL to WebGPU: A perspective from Babylon js by David Catuhe视频的12:51开始,演示了WebGPU和WebGL的渲染性能对比的Demo(WebGPU应该也采用了缓存机制),下面我们来详细分析下差异的原理:
如上图所示,我们看到在当前场景中,两者的FPS差不多,这是为什么呢?
我们已经知道,影响FPS性能的因素为:CPU传递DrawCall时间+GPU时间
目前在屏幕上绘制的物体较少,所以DrawCall次数很少,所以CPU传递DrawCall时间很少;
所以一帧的时间主要花费在GPU时间上。然而对于WebGPU和WebGL,在GPU端都是通过光栅化管线来渲染,所以两者在GPU时间上都是一样的。
所以综上所述,两者的FPS应该是差不多的。
下面看另外的一个场景:
现在因为相机拉的非常远,所以在屏幕上绘制的物体非常多,所以DrawCall次数很多,所以CPU传递DrawCall时间很大,所以使用缓存机制的WebGPU的性能优势就体现出来了。
WebGPU比WebGL快了3倍左右,这与我们的测试结果差不多。
测试“计算”的性能
场景描述
该场景的设计思路为:
在固定分辨率的屏幕当中,用WebGL和WebGPU计算和渲染相同个数的固定大小三角形,三角形个数从小到大进行递增;
所有的三角形首先通过计算算法计算出每个三角形在场景中的位置,然后通过一次DrawCall(Instancing)渲染到屏幕中。
此算法的思路是:每一个三角形的位置的获得都需要遍历场景中其他所有三角形的位置,最终算法会收敛成为三角形群聚现象,模拟类似于鸟群的飞行状态。这里需要特殊说明,算法本身只是为了体现测试场景的计算量,不同的算法并不会对测试结果的整体趋势产生任何影响。
具体的场景效果如下图:
结果分析
1)硬件环境为13”MacBook M1:
- 影响CPU性能的因素:CPU计算时间(因为只有一次DrawCall,所以“CPU传递DrawCall时间”几乎为0,故该项忽略不计)
- WebGL:物体数量低于500时,在计算每一个物体的位置和运动轨迹时,虽然需要遍历其他所有三角形的状态(测试算法的效果),但是由于物体数量较少,CPU的计算任务仍然可以在16ms以内完成。但是超过500个物体后,CPU的耗时明显增加。原因是,CPU的主要运算时间都在计算物体在下一时刻的位置,随着物体数量的增加,需要遍历的次数也随之线性增加。
- WebGPU:在测试范围内,CPU耗时几乎为0。原因是WebGPU标准定义了计算着色器(Compute Shader),使得WebGPU可以将所有的计算任务全部交给GPU的Compute Shader来完成,而不需要CPU参与计算任务。因此可以看出WebGPU,在计算场景中,同样释放了CPU的运算负担,极大得提高了性能。
- 影响FPS性能的因素:CPU计算时间 + GPU时间
- WebGL:物体数量低于500时,几乎可以保持在60FPS的状态。但是当物体数量超过500时,FPS表现迅速下降。因为CPU大量的时间都消耗在了计算每个物体的位置上,随着物体数量的增加,需要遍历的物体越多,因此计算耗时越多,帧率下降明显。而且当超过一定物体数量时,由于计算量过大,出现了测试崩溃(大于3000个物体)。
- WebGPU:由于有了计算着色器(Compute Shader),所以所有的计算都交给了GPU去完成。由于GPU的Compute Shader具有并行计算的特征,可以非常快地完成这种复杂的计算任务,因此FPS可以大部分时间都保持在60FPS的状态。但是当测试达到15000个物体时,也达到了M1的GPU运算能力上限,因此也会出现FPS下降。
2)硬件环境为台式机i7-4790 + RTX 2060 Super:
- 影响CPU性能的因素:CPU计算时间(因为只有一次DrawCall,所以CPU传递DrawCall时间的几乎为0,故该项忽略不计)
- WebGL:物体数量低于500时,由于物体数量较少,台式机CPU的计算任务和M1配置一样,也可以在16ms以内完成。但是超过500个物体后,CPU的耗时明显增加。原因与M1环境下的原因相同。
- WebGPU:其整体趋势和M1环境下对比分析相同
- 影响FPS性能的因素:CPU时间 + GPU时间
- WebGL:物体数量低于500时,几乎可以保持在60FPS的状态。但是当物体数量超过500时,FPS表现迅速下降。原因同M1场景分析一致。计算量过大时,测试场景出现崩溃(大于3000个物体)。
- WebGPU:其整体趋势和M1环境下对比分析相同。当测试达到35000个物体时, FPS开始下降,因为达到了RTX显卡的运算能力上限。
测试结论
在当前计算场景的测试中得出如下结论:
- WebGPU采用了计算着色器,可以直接调用GPU能力,通过并行计算完成复杂的计算场景。而WebGL只能把计算任务交给CPU来处理,效率较低。相比较WebGL,WebGPU在M1配置下计算性能提升50倍,台式机i7-4790 + RTX 2060 Super配置下,计算性能提升100倍。
- CPU性能对比中,WebGL下,M1配置的CPU耗时参数优与台式机的CPU耗时参数,因此台式机CPU(i7-4790)性能表现不如M1芯片性能。同样在FPS性能对比中,WebGL下,台式机的计算还是体现在CPU方面,即使拥有RTX显卡也无法利用其计算能力。但是不论硬件配置如何,CPU性能的表现和FPS性能的表现,在WebGL下和WebGPU下,整体变化趋势一致。WebGPU性能整体明显优与WebGL性能。