WebGPU:在瀏覽器中解鎖現代 GPU 訪問
近日,Chrome 支持了 WebGPU,新的 WebGPU API 在圖形和機器學習工作負載方面實現了巨大的性能提升。本文將探討 WebGPU 如何改進當前 WebGL 解決方案,并展望未來的發展方向。
WebGPU 背景
WebGL 于 2011 年登陸 Chrome。通過允許 Web 應用利用 GPU,WebGL 可以在 Web 上實現驚人的體驗——從 Google 地球到交互式音樂視頻,再到 3D 房地產等等。WebGL是基于OpenGL系列API開發的,該API最初開發于1992年,自那時以來 GPU 硬件已經發生了極大的變化。
為跟上這一進步,一種新型的API被開發出來,以更高效地與現代GPU硬件交互。這些API包括Direct3D 12、Metal和Vulkan。這些新的 API 支持GPU編程的新的和苛刻的用例,例如機器學習的爆炸式增長和渲染算法的進步。WebGPU 是 WebGL 的繼承者,將這種新型現代 API 的進步帶到了 Web。
WebGPU 在瀏覽器中解鎖了許多新的 GPU 編程可能性。它更好地反映了現代 GPU 硬件的工作方式,并為未來更高級的GPU功能奠定了基礎。自2017年以來,這個API已經在W3C的“Web GPU”小組中不斷完善,并得到了包括蘋果、谷歌、Mozilla、微軟和英特爾在內的眾多公司的合作。經過 6 年的努力,很高興地宣布,這項對 Web 平臺最大的增強功能終于可用了!
WebGPU 現在可以在 Chrome OS、macOS和Windows上的Chrome 113中使用,其他平臺也將會很快推出。
下面來看一些令人興奮的 WebGPU 使用案例。
解鎖用于渲染的新 GPU 工作負載
諸如計算著色器之類的 WebGPU 功能使新類別的算法能夠移植到 GPU 上。例如,可以為場景添加更多動態細節、模擬物理現象等算法!甚至以前只能用 JavaScript 完成的工作負載現在可以轉移到 GPU 上。
以下視頻顯示了用于對這些元球表面進行三角測量的行進立方體算法。在視頻的前 20 秒內,當該算法在 JavaScript 中運行時,它很難跟上僅以 8 FPS 運行的頁面,從而導致動畫卡頓。為了在 JavaScript 中保持高性能,需要大量降低細節級別。
當我們將相同的算法移動到計算著色器時,這是一個白天和黑夜的區別,這在 20 秒后的視頻中可以看到。性能顯著提高,頁面現在以 60 FPS 的流暢速度運行,并且對于其他效果仍有很大的性能提升空間。此外,頁面的主要 JavaScript 循環完全釋放出來用于其他任務,確保與頁面的交互保持響應。
WebGPU 還可以實現以前不實用的復雜視覺效果。在以下示例中,在流行的 Babylon.js 庫中創建,海洋表面完全在 GPU 上模擬。逼真的動態是由許多相互添加的獨立波創建的。但是直接模擬每個波浪太昂貴了。
這就是演示使用稱為快速傅立葉變換的高級算法的原因。這不是將所有波表示為復雜的位置數據,而是使用更有效地執行計算的光譜數據。然后每一幀使用傅立葉變換將光譜數據轉換為代表波浪高度的位置數據。
更快的 ML 推理
WebGPU 還可用于加速機器學習,這已成為近年來 GPU 的主要用途。
長期以來,創發人員一直在重新利用 WebGL 的渲染 API 來執行非渲染操作,例如機器學習計算。然而,這需要繪制三角形的像素作為啟動計算的一種方式,并仔細打包和解包紋理中的張量數據,而不是更通用的內存訪問。
以這種方式使用 WebGL 需要開發人員笨拙地使他們的代碼符合專為繪圖而設計的 API 的期望。再加上缺乏計算之間的共享內存訪問等基本功能,這會導致重復工作和次優性能。
計算著色器是 WebGPU 的主要新功能,可以消除這些痛點。計算著色器提供更靈活的編程模型,利用 GPU 的大規模并行特性,同時不受嚴格的渲染操作結構的限制。
計算著色器為在著色器工作組內共享數據和計算結果提供了更多機會,以提高效率。與之前出于相同目的使用 WebGL 的嘗試相比,這可能會帶來顯著的收益。
作為這可以帶來的效率提升的一個例子,TensorFlow.js 中圖像擴散模型的初始端口顯示,當從 WebGL 移動到 WebGPU 時,各種硬件的性能提升了 3 倍。在一些測試過的硬件上,圖像渲染時間不到 10 秒。因為這是一個早期的端口,相信 WebGPU 和 TensorFlow.js 都有更多改進的可能!
但 WebGPU 不僅僅是將 GPU 功能帶到 Web 上。
首先為 JavaScript 設計
WebGPU是在對WebGL開發人員十年的工作經驗進行反思的基礎上開發的。將他們遇到的問題、遇到的瓶頸和提出的問題整理出來,并將所有反饋匯總到這個新的API中。
WebGL 的全局狀態模型使得創建強大、可組合的庫和應用變得困難和脆弱。因此,WebGPU大大減少了開發人員需要跟蹤GPU命令時需要跟蹤的狀態數量。
調試 WebGL 應用是很痛苦的,因此WebGPU包括了更靈活的錯誤處理機制,不會降低性能。而且確保從API中獲得的每條消息都易于理解和可操作。
頻繁調用過多的 JavaScript 函數會成為復雜 WebGL 應用的瓶頸。因此,WebGPU API 的通信量較少,因此可以用更少的函數調用完成更多的任務。專注于在前期執行重量級驗證,盡可能使關鍵的繪制循環精簡。提供了像渲染捆綁一類的新 API,它允許預先記錄大量的繪圖命令,并以單個調用重播它們。
為了展示像渲染捆綁這樣一個功能會帶來多么大的變化,下面是Babylon.js的另一個演示。他們的 WebGL 2 渲染器可以每秒執行約 500次 JavaScript 調用以呈現這個美術館場景。
然而,他們的 WebGPU 渲染器啟用了一項稱為快照渲染的功能。此功能構建在 WebGPU 渲染包之上,可使提交相同場景的速度提高 10 倍以上。這種顯著減少的開銷使 WebGPU 能夠呈現更復雜的場景,同時還允許應用使用 JavaScript 并行執行更多操作。
現代圖形 API 以復雜性、以簡單性換取極端優化機會而著稱。另一方面,WebGPU 專注于跨平臺兼容性,在大多數情況下自動處理資源同步等傳統難題。
WebGPU 易于學習和使用。它依賴于網絡平臺的現有功能來進行圖像和視頻加載等操作,并依賴于眾所周知的 JavaScript 模式,例如用于異步操作的 Promises。這有助于將所需的樣板代碼數量保持在最低限度。可以用不到 50 行代碼在屏幕上顯示第一個三角形。
<canvas id="canvas" width="512" height="512"></canvas>
<script type="module">
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const context = canvas.getContext("webgpu");
const format = navigator.gpu.getPreferredCanvasFormat();
context.configure({ device, format });
const code = `
@vertex fn vertexMain(@builtin(vertex_index) i : u32) ->
@builtin(position) vec4f {
const pos = array(vec2f(0, 1), vec2f(-1, -1), vec2f(1, -1));
return vec4f(pos[i], 0, 1);
}
@fragment fn fragmentMain() -> @location(0) vec4f {
return vec4f(1, 0, 0, 1);
}`;
const shaderModule = device.createShaderModule({ code });
const pipeline = device.createRenderPipeline({
layout: "auto",
vertex: {
module: shaderModule,
entryPoint: "vertexMain",
},
fragment: {
module: shaderModule,
entryPoint: "fragmentMain",
targets: [{ format }],
},
});
const commandEncoder = device.createCommandEncoder();
const colorAttachments = [
{
view: context.getCurrentTexture().createView(),
loadOp: "clear",
storeOp: "store",
},
];
const passEncoder = commandEncoder.beginRenderPass({ colorAttachments });
passEncoder.setPipeline(pipeline);
passEncoder.draw(3);
passEncoder.end();
device.queue.submit([commandEncoder.finish()]);
</script>
總結
很高興看到 WebGPU 為 Web 平臺帶來的所有新可能性,圍繞 WebGL 構建了一個充滿活力的庫和框架生態系統,并且同樣的生態系統渴望擁抱 WebGPU。在許多流行的 Javascript WebGL 庫中,對 WebGPU 的支持正在進行中或已經完成,在某些情況下,利用 WebGPU 的優勢可能就像更改單個標志一樣簡單!
Chrome 113 中的第一個版本只是一個開始。雖然初始版本適用于 Windows、ChromeOS 和 MacOS,但計劃在不久的將來將 WebGPU 引入其余平臺,如 Android 和 Linux。
致力于推出 WebGPU 的不僅僅是 Chrome 團隊。Firefox 和 WebKit 的實現也在進行中。
此外,W3C 已經在設計新功能,這些功能在硬件可用時可以公開。例如:在 Chrome 中,計劃很快在著色器和 DP4 類指令中啟用對 16 位浮點數的支持,以進一步提高機器學習性能。
WWebGPU是一個廣泛的API,其以釋放驚人的性能。本文只能對其優點進行概述,但如果想親身體驗WebGPU,可以查看入門 Codelab《Your first WebGPU app[1]》,將構建經典康威生命游戲的GPU版本。這個 Codelab 會逐步引導完成整個過程,因此即使第一次進行GPU開發,也可以輕松嘗試。
參考:https://developer.chrome.com/blog/webgpu-io2023/
相關鏈接
[1]Your first WebGPU app: https://codelabs.developers.google.com/your-first-webgpu-app