WebGPU 導入[1] - 入門常見問題與個人分享


1. 常見問題

① WebGL、ThreeJS 會淘汰嗎?WebGL 是不是過時了?WebGPU 性能是不是比 WebGL 強?

ThreeJS 會淘汰嗎?

ThreeJS、BabylonJS 兩個應用級 3D 庫一直在設計 WebGPU 爲底層的新渲染器,後者尤爲積極。

什麼是應用級?這兩個庫都屏蔽了 WebGL 的底層調用細節,大多數時候,你編寫的代碼更專注於“場景”中的“三維物體”的位置,加載“模型文件”,高級點的會寫漂亮的“材質”。這些帶引號的概念,在 WebGL 底層接口都是沒有的,是實時渲染技術的一些概念在 JavaScript 中的實現。

如果你是應用級別的開發者,不關心這些庫如何封裝底層圖形 API,那現在大可不必入場,等正式發佈再瞭解也不遲,畢竟這兩個受衆這麼廣的庫,爲了保持穩定性,在上層封裝上不會短時間內進行激進改動。

WebGL 會淘汰嗎?WebGL 是不是過時了?

短時間內不會,至少 10 年內。不信你看看 Java8?(開個玩笑)

WebGL 1.0 發佈至今已有 10 年,完全落實 WebGL 2.0 的實現也才一年(截至發文),有很多作品、程序依舊在用基於 WebGL 技術族運行着,發光發熱。借用馬克思主義哲學的一個原理,是說“舊事物在它的作用沒有完全發揮出來之前是絕不會自行消亡的,舊事物當中除了消極因素,依然存在積極因素”。

WebGL 的“全局狀態”機制繼承自 OpenGL,有大量的資料可供查詢,大量的案例仍存於互聯網中。

WebGPU 的性能是不是比 WebGL 強?

有一部分人被 WebGPU 吸引過來的原因是“跨平臺 + 性能”這對組合。

誠然,WebGL 對比 Canvas2D 繪圖技術的性能,是直接碾壓的,在這十年中給 Web 前端帶來了高性能的可能,但是長時間的實踐下來,有的人發現了“WebGL 程序有時候,並不是那麼快,甚至卡的要死”,他們 也許不會深究底層原因,直接寄希望於一個他們認爲的新的王:WebGPU,這其實是一種很不唯物主義的、非常唯心主觀的看法。

WebGPU 從設計上來看,確實有不少特徵是優於 WebGL 的,列舉如下:

  • PromiseAPI / async + await 的異步語法加入:對網絡數據加載、解碼等同步耗時操作有了更好的支持,一定程度上避免了回調地獄問題

  • 面向對象的 API 設計:相對於 WebGL API 的過程式調用,選項式圖形 API 的使用更科學

  • 不再使用全局狀態機制:使用指令緩衝節約了 CPU 到 GPU 之間的信息傳遞成本,要知道 WebGL 切換某個狀態(例如紋理、着色器程序),就是在切換全局狀態對象,這個在微觀上是比較耗時的,而 60 幀速率的每一幀只有 16.67 毫秒左右,能在微觀節約每一點每一滴的時間,累計起來就不少了

  • 原生支持計算管線、計算着色器:WebGL 磨磨蹭蹭實現的 GPU 並行計算功能直接提供出來,並與渲染管線地位對等

但是這些僅僅是在底層的對話基礎上比 WebGL 強,這些底層解決的問題,不一定是有的朋友的“性能問題”。譬如,在應用層、代碼邏輯層可能會有這些原因導致了“性能問題”:

  • 單幀時間內,JavaScript 代碼的解釋運行的性能消耗遠超 GPU 渲染耗時,導致 rAF 一幀大於 16.67 毫秒,這個時候應該反思在 JavaScript 這一側各路函數調用耗時多久;這種情況可能是數據編解碼耗時、頻繁 new 了複雜對象、使用了繁重的 for 循環等;

  • 着色器中使用了過量的燈光、巨大的貼圖,也就是即便在 JavaScript 一側進行了數據選擇、剔除後,仍然讓 GPU 執行負擔較重的邏輯、硬件採樣計算(而不是它擅長的簡單並行運算)

  • 單幀內頻繁切換狀態數據(着色器對象、紋理、頂點緩衝等),導致過多的 DrawCall

  • 低端性能的硬件想玩複雜的應用場景;高估了瀏覽器 JavaScript 的性能、瀏覽器能調用的內存大小

所以說,一味寄希望於新的王,而不從實際出發審視問題,是解決不了問題的

② WebGPU 什麼時候能用?怎麼才能用 WebGPU?我學習 WebGPU 需要什麼條件?

WebGPU 什麼時候能用?

WebGPU 標準是多個大技術團體相互制衡、妥協的產物,包括但不限於微軟、蘋果、谷歌等。官方一直在拖延 1.0 版本的發佈時間,保守估計 2022 年第四季度上線三大瀏覽器正式版是最快的結果了,不保守估計可能還要到 2023 年上半年。

怎麼才能用 WebGPU?

當前,推薦在以下 PC 端瀏覽器試用 WebGPU 及其着色器語言 WGSL:

  • Google Chrome,使用 Canary 頻道(即金絲雀)

  • Microsoft Edge,使用 Canary 頻道(內核與 Chrome 同宗)

  • Firefox,使用 Nightly 頻道

  • Safari,使用 Technology Preview 頻道

雖然正式頻道也能用,但是在沒發佈 1.0 版本之前,都要去申請一個 Origin Trial Token 寫在 HTML 代碼中,筆者覺得麻煩,當然讀者也可以選擇配置這個在正式版瀏覽器中使用。

移動端、Linux 系統恐怕還要等好久(5年後?)。

我學習 WebGPU 需要什麼條件?

學習 WebGPU,你要有這樣的硬件儲備:

  • 一臺 Windows / macOS 電腦,能運行上述瀏覽器

  • 一些輸入設備,例如鼠標鍵盤

你還需要這樣的編程知識儲備:

  • 合格的 ES6 語法使用習慣,尤其是新的變量聲明關鍵詞 const/let、箭頭函數、類、反引號字符串、PromiseAPI,最好能用到 ES7 的異步語法 async/await

  • 一款趁手的代碼編輯器,我習慣 VSCode;

  • 知道怎麼使用 HTTP 協議打開你的頁面,運行 HTTP 協議下的 JavaScript 代碼,而不是愚蠢的雙擊 .html 文件用 File 協議打開,你可以使用 VSCode 的 Live-Server 插件,也可以用 Python 調起 HTTP 服務,也可以用 Nginx 等 Web 服務器軟件,甚至用前端工具提供的開發服務器;

  • 最好掌握簡易的立體解析幾何(求向量夾角、點線距離等)、線性代數基本功(行列式與向量常規運算)、3D 空間變換與矩陣的基礎知識

你可能不需要掌握,但是會了如虎添翼的技能:

  • 主流前端框架與各大打包器的基本使用與運行關係,例如 Webpack 是如何用 loader 處理各種資源文件的、vite 等工具的“路徑”問題、避免前端框架的性能弱點用法等

  • 常用設計模式的使用

  • 基於 NodeJS 包機制的前端工程與瀏覽器應用程序的關係,瞭解 JavaScript 的運行時環境、JavaScript 模塊化規範

  • 使用瀏覽器進行 Web 前端開發三大硬技能:網絡請求面板(看請求消耗和抓包)、源代碼調試面板(儘量用斷點替代 console.xxx)、性能測試面板的使用(精準分析性能問題)

  • 一定的實時渲染技術積累:這個對於老鳥來說可能會心一笑,但是對於新手來說可能有點蒙,別急,在下面 1.4 小節會細談

③ WebGPU 有什麼用?它解決了什麼問題?

WebGPU 有什麼用?

WebGPU 是一個跨平臺的圖形 API 規範,目前能提供的功能有:

  • 渲染繪圖

  • 跨平臺調用 GPU 並行計算

前文提及的“計算管線”對應這裏的第二點,而沿襲自 WebGL —— 準確的說 GPU 從 CPU 分離之初的首要目的,即“渲染繪圖”功能,則是對應了 WebGPU 的“渲染管線”。

我認爲,WebGPU 最大的作用可能並不體現在渲染管線上,畢竟它只是對三大原生圖形 API 的封裝,渲染這方面由 WebGL 實踐了這些年,在瀏覽器上的表現可能已經沒有特別驚豔的效果提升了,解決的應該只是 1.1 小節中的各種底層問題;

最大的作用反而應該是較之於 WebGL 更易用的 GPU 並行計算功能,也就是計算管線的新設計。

補充 1.1 小節中 WebGPU 比 WebGL 更先進的 2 個點:

  • 脫離 Canvas 元素的依賴,繪圖時才需要配置上下文對象與 HTMLCanvasElement 的關係,令 Canvas 作爲繪圖的容器,也就是一個比較特殊的紋理

  • 因爲不再強依賴於 Canvas,而是直接從瀏覽器的 navigator 全局對象上調取 GPU 的使用,所以可以在 WebWorker 中使用 WebGPU,跳出主線程訪問 GPU 的能力,進一步增強了 CPU 側的調度能力(不過就目前來看,這一點優化還不是太好的樣子)

第一點就是 WebGPU 計算管線的底氣。

當下,使用 GPU 進行深度學習、機器學習的應用有不少,以往想通過 JavaScript 來完成 GPGPU 實在是太麻煩了。WebGPU 允許更好地擺脫瀏覽器環境 —— 當然,在瀏覽器環境中,我也可以不參與繪圖,使用計算管線就可以做出很多有趣的事情來,不僅僅是 DL、ML。

讀者可能知道,如果不知道就當聽故事,除了瀏覽器、NodeJS,有一個叫 Deno 的工具也是 JavaScript 的運行時,它內置了 Firefox 瀏覽器的 WebGPU 實現成果,也就是 Wgpu 庫,Wgpu 使用 Rust 語言實現 WebGPU 規範。

也就是說,Deno 是可以運行 WebGPU 的,雖然它不具備瀏覽器的多數功能,但是它就是能調起 WebGPU,調用計算管線,完成並行計算。

WebGPU 的實現還有幾個,Chrome 和 Edge 在用的是 Google 的 Dawn 項目,使用 C++ 實現 WebGPU 規範,蘋果 Safari 是自己家的內核更新實現 —— 這些就是瀏覽器能調用三大圖形 API 的底層原因。

如果你願意,你也可以把 Dawn 或者 Wgpu 拉下來,直接使用 C++ 或 Rust 來調用這些實現,而不是要經過 JavaScript 運行環境。

它解決了什麼問題?

在 1.1 小節和本小節已做出解釋,它解決的是 WebGL 長期以來的底層技術問題,把各大廠商安頓好了,在圖形技術上達成了一致,建立起新的技術壟斷(不是

④ 學了 WebGPU 是不是能寫出好看的效果?

這個問題和“會用廚具能不能做出一桌好菜”一樣。

WebGPU 和 WebGL,甚至底層的 D3D、Metal、Vulkan 乃至 OpenGL 一樣,只是一套調用 GPU 的接口。想要從機械的 GPU 繪圖動作,枯燥的 Buffer、紋理貼圖、狀態值中實現光彩奪目、栩栩如生的渲染效果,還需要結合實時渲染(RealTimeRendering)、圖像處理、光線追蹤等衆多技術。

有一個分享着色器特效的網站,叫 Shadertoy,上面有很多使用片元着色器實現的好看效果,這就是一個典型的例子,它就沒有讓開發者寫什麼 WebGL、WebGPU、ThreeJS,你只需要遵守它的規則,就可以實現很多好看的東西 —— 前提是,這些實現,都是基於上面說的非 API 技術的。

例如,下面幾個入門、進階“效果”,嚴格來說與 WebGL、WebGPU 這些圖形 API 無關:

  • 點光、環境光、聚光、平行光等光源的使用

  • 各種陰影技術

  • 各類材質實現

  • 後處理圖像算法,例如模糊、環境光遮蔽

雖然無關,但是實現起來或多或少離不開這些圖形 API —— 我想說的是看待的時候應該界限分明,學的時候又不應該孤立看待。WebGPU 作爲一種跨平臺標準,一種 API,它是工具屬性,並不是“好看效果”的招牌、核心

⑤ WebGPU 有缺點嗎?

當然有。

  • 1.0 制定時間略長,從 2021 年望到 2022,眼看可能要到 2023

  • 資料太少了,尤其是中文資料,不知道是瞭解的人不多,還是大佬不屑於寫

  • 原來的 WebGL 技術和資料不能低成本遷移,例如新舊概念的更替、着色器代碼的移植

  • 兼容性是一個很漫長是事情,望天

  • 對於應用層開發者來說,沒有能馬上就用的封裝庫和足夠的例子,也許推廣起來比較困難,前人還未栽樹,後人甚至還得開荒

所以,可預見的估計,哪怕今年年底能發佈 1.0 版本,想要廣泛應用這套標準於繪圖渲染,保守估計都要等 3 年以上,用戶的瀏覽器可能更新得並沒有那麼勤快。

2. 一些看法與分享

這部分結合了唯物辯證法。

① 使用分析與綜合的辯證思維,全面、聯繫地看問題

圖形 API 應與實時渲染、圖像處理等技術分開看待,但是不能忽略它們的緊密聯繫。

大多數人不缺綜合的能力,而是缺少系統的分析的能力,不喜歡把事物細緻剖析成各個具體的細小環節來研究。

就舉兩個例子:

  • 好多人在學習 WebGL 時沒有界清哪一部分屬於 API 規範函數的使用,哪一部分屬於渲染技術的代碼實現,哪一部分屬於基礎的空間立體幾何變換,就把鍋甩給“WebGL和3D好難”這個結論上,以至於現在學習 WebGPU 也可能有這個毛病

  • GIS 行業中,好多團隊沒有分析清楚想做什麼,需要用什麼,喜歡堆砌、翻新名詞和概念,不喜歡落實到既有技術,結果就是“藍圖是國畫,實施是草圖,產出是垃圾”

分析和綜合的功力,區別在於深淺、邏輯、科不科學、系不繫統上。

② 具體問題具體分析,抽象和具體應該結合在一起

簡單的說,就是在合適的範圍,說對應的語言。筆者曾經在討論時遇到很多技術水平不對等的交流,舉個例子:

輕量化三維模型以提高性能。

這句話是一句濃縮了很多技術細節的話:“輕量化”是一個可以由多階段、多目的構成的技術棧,“性能”也有諸多因素構成,可以說是“抽象”。

但是很多工作執行時,雖然以抽象概念爲引領,但是我們必須結合具體的條目、具體的細節、技術,才能完成抽象概念想達成的目的。

用機關槍式的提問方法:輕量化三維模型的什麼?輕量化是壓縮數據文件的體積嗎?是減少三維模型的三角面,還是壓縮貼圖,還是使用更高效的信息編碼技術?

“性能”如何定義?是幀速率、網絡請求併發量、內存佔用量、網絡傳輸時間?

總而言之,抽象的概念就應該在大的領域定向,而在小的範圍內應該定量、具體地溝通與交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章