我们可以通过在一秒钟内调用JavaScript普通函数的次数来测试其性能。但是,在WebGL中,像gl.drawArrays
这样的函数是异步的,因此无法通过测试API调用的时间来测量着色器所需的时间。
那么有没有办法来测试WebGL函数的性能呢?
我们可以通过在一秒钟内调用JavaScript普通函数的次数来测试其性能。但是,在WebGL中,像gl.drawArrays
这样的函数是异步的,因此无法通过测试API调用的时间来测量着色器所需的时间。
那么有没有办法来测试WebGL函数的性能呢?
由于着色器的上下文非常复杂且非常特定于GPU,因此很难对其进行基准测试。
您可以在使用某个着色器绘制大量的东西(几千到几百万次绘制调用)之前和之后使用performance.now
,然后通过调用gl.readPixels
来阻塞GPU,以判断一个着色器是否比另一个快。它会告诉你哪个更快。但是它不会告诉您它们有多快,因为阻塞GPU包括起始和阻塞时间。
想象一辆赛车。对于直线赛车,您计时加速度到达目的地。对于赛车,您计时以全速完成的一圈。您让车先行驶一圈,然后计时第二圈,车以全速穿过起点和终点。因此,您可以得出车的速度,而对于直线赛车,您获得了它的加速度(通常与GPU无关,因为如果您追求速度,则永远不应该启动和停止它们)。
另一种在不添加启动/停止时间的情况下计时的方法是在requestAnimationFrame
帧之间绘制一堆东西。不断增加数量,直到帧之间的时间跳跃了整个帧。然后比较着色器之间的数量。
实际使用中还有其他问题。例如,像许多移动设备上的PowerVR这样的瓦片GPU会尝试剔除将被覆盖的基元的部分。因此,在非瓦片GPU上具有大量重叠绘制的重型着色器可能在瓦片GPU上非常快。
此外,请确保您正在计时正确的内容。如果您正在计时顶点着色器,则可能希望将画布设置为1x1像素,将片段着色器尽可能简单,并传递许多顶点以进行一次绘制调用(以消除调用时间)。如果您正在计时片段着色器,则可能需要一个大画布和一组包含几个完整画布四边形的顶点。
还请参见WebGL/OpenGL:性能比较。
EXT_disjoint_timer_query
的扩展,它允许测量绘制调用的执行时间,这在很大程度上取决于着色器执行时间,尤其是当您的着色器非常复杂时(因此占用了GPU执行绘制调用的大部分时间)。