我已经在WebGL中编写了GPU路径跟踪器,并希望查看渲染单个帧需要多长时间。我该如何在台式机和移动浏览器上进行移植?
我对如何执行此操作有一些想法,但都无济于事:
想法1:测量完成之间的延迟时间:
gl.finish(); var t0=performance.now();
//(render)
gl.finish(); var t1=performance.now();
var latency = 0.001*( t1 - t0 );
这不起作用! Chrome(在用途上极其错误地)aliases gl.finish()
到gl.flush()
,因此测得的延迟与完成的工作几乎没有关系。
想法2:Use EXT_disjoint_timer_query
/ EXT_disjoint_timer_query_webgl2
:
这不起作用! {@ 3}在Rowhammer式攻击中被滥用,因此can be used。
想法3:使用performance.now()
测量两次调用window.requestAnimationFrame(...)
的时间。
这不起作用!由于渲染成本很高,出于功率/热量的原因,我仅在发生某些更改(例如相机位置)时才重新绘制帧。因此,所测得的延迟可能会很大(并且无论如何都会在下一个帧中报告)。
答案 0 :(得分:1)
您无法从浏览器内部检查延迟。无法知道图像何时真正出现在屏幕上。浏览器可能是双缓冲或三缓冲的,操作系统本身通常具有复合步骤,因此如果用户在电视上进行帧插值也可能添加帧,则可以添加帧。也许您实际上并不是要测量“延迟”,但是如果您确实要测量“延迟”,则只能使用外部设备进行测量。
即使在OpenGL中,也无法直接使用gl.finish
测量渲染时间。您将不会测量“渲染”时间。您将测量“启动时间” +“渲染时间” +“停止时间”,因此您可以使用gl.finish
来确定一种技术是否比另一种更快,但是您不能使用gl.finish
找出帧的速度,因为在正常操作中,图形是流水线的,跨多个线程或进程运行。调用gl.finish
会增加同步这些线程和进程的开销,这可能不仅仅是渲染。
您可能会使用gl.finish定时来渲染最小的东西(单个1像素三角形的纯色)。用它来测量“同步”多个线程的开销,并从较长渲染的较长时间中减去该时间,但即使在平铺架构GPU上也存在问题,因为平铺架构GPU使用了避免过度绘制的技术。
换句话说,如果您在传统GPU上绘制2个重叠的不透明三角形,则将绘制两个三角形的每个像素,但在平铺的GPU上,重叠像素将仅绘制一次。这意味着单独定时绘制特定图形不会告诉您它们组合时的速度。
在任何情况下,您都可以通过调用gl.finish
来模拟gl.readPixels
(使所有进程陷入僵局)来读取单个像素,因为为了使该像素到达JavaScript,必须停止并同步所有进程
如上所述,您应该首先绘制一个像素来测量同步过程的开销,然后从测量中减去该时间。
您也不应该使用第一个测量值并绘制几次,因为许多事情都是延迟初始化的,因此您进行任何内容的第一个渲染都可能比第二个渲染慢。
因此,步骤将类似于
第2步和第3步将强制执行任何隐藏的初始化,因此请确保在第2步和第3步中使用了所有资源,使用了所有纹理,使用了所有缓冲区,等等。