簡體   English   中英

WebGL / OpenGL:比較性能

[英]WebGL/OpenGL: comparing the performance

出於教育目的,我需要比較WebGL與OpenGL的性能。 我有兩個用WebGL和OpenGL編寫的等效程序,現在我需要考慮它們的幀速率並進行比較。

在Javascript中,我使用requestAnimationFrame進行動畫處理,我注意到它會導致幀速率始終為60 FPS,並且只有在我切換制表符或窗口時它才會下降。 另一方面,如果我總是以遞歸方式調用渲染函數,則窗口會因顯而易見的原因而凍結。

這就是我采用FPS的方式:

var stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '450px';
stats.domElement.style.top = '750px';

document.body.appendChild( stats.domElement );

setInterval( function () {

    stats.begin();
    stats.end();
}, 1000 / 60 );


var render= function() {
    requestAnimationFrame(render);
    renderer.render(scene,camera);
}

render();

現在問題是如果總是60 FPS的場景,我實際上無法將它與OpenGL的幀速率進行比較,因為OpenGL僅在以某種方式修改時重繪場景(例如,如果我旋轉對象)並且glutPostRedisplay()得到調用。

所以我想如果WebGL中有一種方法只在必要時重繪場景,例如當旋轉對象或者着色器中的某些屬性被更改時。

您無法通過推送幀來直接比較WebGL中GPU的幀速率。 相反,你需要弄清楚你可以在一個框架內完成多少工作。

所以,基本上選擇一些目標幀率,然后繼續做更​​多的工作,直到你超越你的目標。 當你達到你的目標時,你可以做多少工作。 您可以使用相同的技術將其與其他機器或GPU進行比較。

有些人會建議使用glFinish來檢查時間。 不幸的是,這實際上並不起作用,因為它會停止圖形管道並且停止本身並不是通常在真實應用程序中發生的事情。 這可能就像汽車從A點到B點的速度有多快,但不是在A之前很久就開始,而是在B之后很久結束,在你到達B之前猛踩剎車並測量你到達B的時間。時間包括減速所需的所有時間,這在每個GPU上是不同的,在WebGL和OpenGL之間是不同的,甚至對於每個瀏覽器也是不同的。 你無法知道花費了多少時間是放慢速度所花費的時間以及花在你實際想要測量的事情上花了多少時間。

所以相反,你需要全程全速前進。 就像一輛汽車一樣,在你到達A點之前你會加速到最高速度,並且在你通過B之前一直保持最高速度。同樣的方式,他們會在排位賽中計時賽車。

您通常不會通過關閉休息時間來停止GPU(glFinish),因此在定時測量中添加停止時間是無關緊要的,並且不會為您提供有用的信息。 使用glFinish你會定時繪圖+停止。 如果一個GPU吸收1秒鍾並且停在2秒而另一個GPU吸收2秒並且停在1,那么兩個GPU的定時將為3秒。 但是如果你在沒有停止的情況下運行它們,那么每秒會抽取3個東西,而另一個GPU每秒只會抽取1.5個東西。 一個GPU顯然更快,但使用glFinish你永遠不會知道。

相反,您可以通過盡可能多地繪制來全速運行,然后測量您能夠完成多少並保持全速。

這是一個例子: http//webglsamples.org/lots-o-objects/lots-o-objects-draw-elements.html

它基本上繪制每一幀。 如果幀速率為60fps,則在下一幀中再抽取10個對象。 如果幀速率小於60fps,則會減少。

由於瀏覽器計時並不完美,您可能會選擇略低的目標(如57fps)來查找它的速度。

最重要的是,WebGL和OpenGL真的只是與GPU對話,而GPU則可以完成真正的工作。 無論WebGL要求GPU執行還是OpenGL,GPU完成的工作都將花費相同的時間。 唯一的區別在於設置GPU的開銷。 這意味着你真的不想畫任何重物。 理想情況下,你幾乎什么都不畫畫。 使您的畫布1x1像素,繪制一個三角形,並檢查時間(如在WebGL中以60fps的速度在WebGL和OpenGL中一次繪制一個三角形的單個三角形)。

但事情變得更糟。 一個真正的應用程序將經常切換着色器,切換緩沖區,切換紋理,更新屬性和制服。 那么,你的時間是多少? 你有多少次能以60fps的速度調用gl.drawBuffers 你能用60fps多少次調用gl.enablegl.vertexAttribPointergl.uniform4fv 有些組合嗎? 什么是合理的組合? 10%調用gl.verterAttribPointer + 5%調用gl.bindBuffer + 10%調用gl.uniform 這些調用的時間是WebGL和OpenGL之間唯一不同的東西,因為最終他們正在與相同的GPU進行通信,而GPU無論如何都將以相同的速度運行。

你實際上不想使用幀率來比較這些東西,因為正如你剛才提到的那樣,由於VSYNC,人為限制為60 FPS。

當使用VSYNC時,所呈現的幀數將受交換緩沖區操作的限制,並且您希望將性能測量中的混亂因素考慮在內。 你應該做的是在幀開始時啟動一個計時器,然后在幀結束時(緩沖區交換之前)發出glFinish (...)並結束計時器。 比較繪制的毫秒數(或計時器測量的任何分辨率),而不是繪制的幀數。

正確的解決方案是在可用時使用ANGLE_timer_query擴展。

引用規范:

歷史上,OpenGL實現幾乎沒有提供有用的時序信息。 應用程序可以通過讀取CPU上的定時器來了解定時,但這些定時器與圖形渲染管道不同步。 讀取CPU計時器並不能保證在讀取計時器之前累積的潛在大量圖形工作完成,因此會產生非常不准確的結果。 glFinish()可用於確定何時完成先前的渲染命令, 但會使圖形管道空閑並對應用程序性能產生負面影響。

此擴展提供了一種查詢機制 ,可用於確定完全完成一組GL命令所需的時間,並且不會拖延渲染管道。 它使用首先在遮擋查詢擴展中引入的查詢對象機制,它允許應用程序異步輪詢時間間隔。

(強調我的)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM