Là một nhà phát triển WebGL, bạn có thể vừa lo lắng vừa hào hứng khi bắt đầu sử dụng WebGPU, phiên bản kế nhiệm WebGL mang đến những tiến bộ của các API đồ hoạ hiện đại cho web.
Bạn có thể yên tâm khi biết rằng WebGL và WebGPU có nhiều khái niệm cốt lõi giống nhau. Cả hai API này đều cho phép bạn chạy các chương trình nhỏ (gọi là chương trình đổ bóng) trên GPU. WebGL hỗ trợ các chương trình đổ bóng đỉnh và mảnh, trong khi WebGPU cũng hỗ trợ các chương trình đổ bóng điện toán. WebGL sử dụng Ngôn ngữ tạo bóng OpenGL (GLSL), còn WebGPU sử dụng Ngôn ngữ tạo bóng WebGPU (WGSL). Mặc dù hai ngôn ngữ này khác nhau, nhưng các khái niệm cơ bản hầu hết đều giống nhau.
Với suy nghĩ đó, bài viết này nêu bật một số điểm khác biệt giữa WebGL và WebGPU để giúp bạn bắt đầu.
Trạng thái chung
WebGL có nhiều trạng thái chung. Một số chế độ cài đặt áp dụng cho tất cả các thao tác kết xuất, chẳng hạn như kết cấu và vùng đệm nào được liên kết. Bạn thiết lập trạng thái chung này bằng cách gọi nhiều hàm API và trạng thái này vẫn có hiệu lực cho đến khi bạn thay đổi. Trạng thái chung trong WebGL là nguồn chính gây ra lỗi, vì bạn rất dễ quên thay đổi một chế độ cài đặt chung. Ngoài ra, trạng thái chung khiến việc chia sẻ mã trở nên khó khăn, vì nhà phát triển cần cẩn thận để không vô tình thay đổi trạng thái chung theo cách ảnh hưởng đến các phần khác của mã.
WebGPU là một API không trạng thái và không duy trì trạng thái chung. Thay vào đó, nó sử dụng khái niệm về một quy trình để đóng gói tất cả trạng thái kết xuất là trạng thái chung trong WebGL. Một quy trình chứa thông tin như nên sử dụng phương pháp kết hợp, cấu trúc liên kết và thuộc tính nào. Một quy trình là bất biến. Nếu muốn thay đổi một số chế độ cài đặt, bạn cần tạo một quy trình khác. WebGPU cũng sử dụng trình mã hoá lệnh để gộp các lệnh lại với nhau và thực thi chúng theo thứ tự đã ghi. Điều này hữu ích trong việc lập bản đồ bóng, chẳng hạn như trong một lần truyền qua các đối tượng, ứng dụng có thể ghi lại nhiều luồng lệnh, một luồng cho mỗi bản đồ bóng của ánh sáng.
Tóm lại, vì mô hình trạng thái chung của WebGL khiến việc tạo các ứng dụng và thư viện có khả năng kết hợp và mạnh mẽ trở nên khó khăn và dễ bị lỗi, nên WebGPU đã giảm đáng kể lượng trạng thái mà nhà phát triển cần theo dõi trong khi gửi lệnh đến GPU.
Không đồng bộ hoá nữa
Trên GPU, việc gửi lệnh và chờ lệnh đồng bộ thường không hiệu quả, vì điều này có thể làm trống quy trình và gây ra bong bóng. Điều này đặc biệt đúng trong WebGPU và WebGL, sử dụng cấu trúc đa quy trình với trình điều khiển GPU chạy trong một quy trình riêng biệt với JavaScript.
Ví dụ: trong WebGL, việc gọi gl.getError()
yêu cầu một IPC đồng bộ từ quy trình JavaScript đến quy trình GPU và ngược lại. Điều này có thể gây ra một bong bóng ở phía CPU khi hai quy trình giao tiếp.
Để tránh những bong bóng này, WebGPU được thiết kế để hoàn toàn không đồng bộ. Mô hình lỗi và tất cả các thao tác khác đều diễn ra không đồng bộ. Ví dụ: khi bạn tạo một hoạ tiết, thao tác này sẽ xuất hiện ngay lập tức, ngay cả khi hoạ tiết đó thực sự là một lỗi. Bạn chỉ có thể phát hiện lỗi không đồng bộ. Thiết kế này giúp hoạt động giao tiếp giữa các quy trình không bị gián đoạn và mang lại hiệu suất đáng tin cậy cho các ứng dụng.
Chương trình đổ bóng điện toán
Chương trình đổ bóng điện toán là những chương trình chạy trên GPU để thực hiện các phép tính cho mục đích chung. Chúng chỉ có trong WebGPU chứ không có trong WebGL.
Không giống như chương trình đổ bóng đỉnh và chương trình đổ bóng mảnh, chương trình đổ bóng điện toán không chỉ giới hạn ở việc xử lý đồ hoạ mà còn có thể dùng cho nhiều tác vụ, chẳng hạn như học máy, mô phỏng vật lý và điện toán khoa học. Chương trình đổ bóng điện toán được thực thi song song bởi hàng trăm hoặc thậm chí hàng nghìn luồng, giúp chúng hoạt động rất hiệu quả trong việc xử lý các tập dữ liệu lớn. Tìm hiểu về điện toán GPU và thông tin chi tiết hơn trong bài viết toàn diện này về WebGPU.
Xử lý khung hình video
Việc xử lý khung hình video bằng JavaScript và WebAssembly có một số nhược điểm: chi phí sao chép dữ liệu từ bộ nhớ GPU sang bộ nhớ CPU và khả năng song song hạn chế có thể đạt được với các worker và luồng CPU. WebGPU không có những hạn chế đó, nên rất phù hợp để xử lý các khung hình video nhờ khả năng tích hợp chặt chẽ với API WebCodecs.
Đoạn mã sau đây cho biết cách nhập VideoFrame dưới dạng một hoạ tiết bên ngoài trong WebGPU và xử lý hoạ tiết đó. Bạn có thể dùng thử bản minh hoạ này.
// Init WebGPU device and pipeline...
// Configure canvas context...
// Feed camera stream to video...
(function render() {
const videoFrame = new VideoFrame(video);
applyFilter(videoFrame);
requestAnimationFrame(render);
})();
function applyFilter(videoFrame) {
const texture = device.importExternalTexture({ source: videoFrame });
const bindgroup = device.createBindGroup({
layout: pipeline.getBindGroupLayout(0),
entries: [{ binding: 0, resource: texture }],
});
// Finally, submit commands to GPU
}
Tính di động của ứng dụng theo mặc định
WebGPU buộc bạn phải yêu cầu limits
. Theo mặc định, requestDevice()
sẽ trả về một GPUDevice có thể không khớp với các chức năng phần cứng của thiết bị thực, mà là một mẫu số chung hợp lý và thấp nhất của tất cả GPU. Bằng cách yêu cầu nhà phát triển yêu cầu giới hạn thiết bị, WebGPU đảm bảo rằng các ứng dụng sẽ chạy trên nhiều thiết bị nhất có thể.
Xử lý canvas
WebGL tự động quản lý canvas sau khi bạn tạo một ngữ cảnh WebGL và cung cấp thuộc tính ngữ cảnh như alpha, antialias, colorSpace, depth, preserveDrawingBuffer hoặc stencil.
Mặt khác, WebGPU yêu cầu bạn tự quản lý canvas. Ví dụ: để đạt được hiệu ứng khử răng cưa trong WebGPU, bạn sẽ tạo một hoạ tiết nhiều mẫu và kết xuất vào đó. Sau đó, bạn sẽ phân giải hoạ tiết nhiều mẫu thành một hoạ tiết thông thường và vẽ hoạ tiết đó lên canvas. Việc quản lý theo cách thủ công này cho phép bạn xuất ra bao nhiêu canvas tuỳ ý từ một đối tượng GPUDevice duy nhất. Ngược lại, WebGL chỉ có thể tạo một ngữ cảnh cho mỗi canvas.
Hãy xem bản minh hoạ WebGPU Multiple Canvases.
Xin lưu ý rằng các trình duyệt hiện có giới hạn về số lượng canvas WebGL trên mỗi trang. Tại thời điểm viết bài này, Chrome và Safari chỉ có thể sử dụng tối đa 16 canvas WebGL cùng lúc; Firefox có thể tạo tối đa 200 canvas. Mặt khác, không có giới hạn về số lượng canvas WebGPU trên mỗi trang.

Thông báo lỗi hữu ích
WebGPU cung cấp một ngăn xếp lệnh gọi cho mọi thông báo được trả về từ API. Điều này có nghĩa là bạn có thể nhanh chóng biết được lỗi xảy ra ở đâu trong mã của mình, điều này hữu ích cho việc gỡ lỗi và khắc phục lỗi.
Ngoài việc cung cấp một ngăn xếp lệnh gọi, thông báo lỗi WebGPU cũng dễ hiểu và có thể hành động. Thông báo lỗi thường bao gồm nội dung mô tả lỗi và các đề xuất về cách khắc phục lỗi.
WebGPU cũng cho phép bạn cung cấp một label
tuỳ chỉnh cho từng đối tượng WebGPU. Sau đó, trình duyệt sẽ dùng nhãn này trong các thông báo GPUError, cảnh báo trên bảng điều khiển và công cụ cho nhà phát triển của trình duyệt.
Từ tên đến chỉ mục
Trong WebGL, nhiều thứ được kết nối bằng tên. Ví dụ: bạn có thể khai báo một biến đồng nhất có tên là myUniform
trong GLSL và lấy vị trí của biến đó bằng cách sử dụng gl.getUniformLocation(program, 'myUniform')
. Điều này rất hữu ích vì bạn sẽ gặp lỗi nếu nhập sai tên của biến đồng nhất.
Mặt khác, trong WebGPU, mọi thứ hoàn toàn được kết nối bằng độ lệch hoặc chỉ mục byte (thường được gọi là vị trí). Bạn có trách nhiệm giữ cho các vị trí của mã trong WGSL và JavaScript luôn đồng bộ.
Tạo mipmap
Trong WebGL, bạn có thể tạo mip cấp 0 của một hoạ tiết rồi gọi gl.generateMipmap()
. Sau đó, WebGL sẽ tạo tất cả các cấp mip khác cho bạn.
Trong WebGPU, bạn phải tự tạo mipmap. Không có hàm tích hợp nào để thực hiện việc này. Hãy xem phần thảo luận về quy cách để tìm hiểu thêm về quyết định này. Bạn có thể sử dụng các thư viện tiện dụng như webgpu-utils để tạo mipmap hoặc tìm hiểu cách tự thực hiện việc này .
Vùng đệm lưu trữ và hoạ tiết lưu trữ
Cả WebGL và WebGPU đều hỗ trợ vùng đệm đồng nhất và cho phép bạn truyền các tham số hằng số có kích thước giới hạn đến các chương trình đổ bóng. Vùng đệm lưu trữ (có vẻ giống với vùng đệm đồng nhất) chỉ được WebGPU hỗ trợ và mạnh mẽ cũng như linh hoạt hơn vùng đệm đồng nhất.
Dữ liệu vùng đệm lưu trữ được truyền đến chương trình đổ bóng có thể lớn hơn nhiều so với vùng đệm đồng nhất. Mặc dù thông số kỹ thuật cho biết các liên kết bộ đệm đồng nhất có thể có kích thước lên đến 64 KB (xem
maxUniformBufferBindingSize
) , nhưng kích thước tối đa của một liên kết bộ đệm lưu trữ ít nhất là 128 MB trong WebGPU (xemmaxStorageBufferBindingSize
).Các vùng đệm lưu trữ có thể ghi và hỗ trợ một số thao tác nguyên tử, trong khi các vùng đệm đồng nhất chỉ ở chế độ chỉ đọc. Điều này cho phép triển khai các lớp thuật toán mới.
Các liên kết vùng đệm lưu trữ hỗ trợ mảng có kích thước thời gian chạy cho các thuật toán linh hoạt hơn, trong khi kích thước mảng vùng đệm đồng nhất phải được cung cấp trong chương trình đổ bóng.
Kết cấu lưu trữ chỉ được hỗ trợ trong WebGPU và là kết cấu mà bộ đệm lưu trữ là bộ đệm đồng nhất. Chúng linh hoạt hơn các hoạ tiết thông thường, hỗ trợ các thao tác ghi truy cập ngẫu nhiên (và cả thao tác đọc trong tương lai).
Thay đổi về vùng đệm và hoạ tiết
Trong WebGL, bạn có thể tạo một vùng đệm hoặc kết cấu rồi thay đổi kích thước của vùng đệm hoặc kết cấu đó bất cứ lúc nào bằng gl.bufferData()
và gl.texImage2D()
tương ứng.
Trong WebGPU, các vùng đệm và hoạ tiết là không thể thay đổi. Điều này có nghĩa là bạn không thể thay đổi kích thước, cách sử dụng hoặc định dạng của các chỉ số này sau khi tạo. Bạn chỉ có thể thay đổi nội dung của các tệp này.
Sự khác biệt về quy ước đặt tên không gian
Trong WebGL, phạm vi không gian cắt Z là từ -1 đến 1. Trong WebGPU, phạm vi không gian cắt Z là từ 0 đến 1. Điều này có nghĩa là các đối tượng có giá trị z là 0 sẽ ở gần camera nhất, trong khi các đối tượng có giá trị z là 1 sẽ ở xa nhất.
WebGL sử dụng quy ước OpenGL, trong đó trục Y hướng lên trên và trục Z hướng về phía người xem. WebGPU sử dụng quy ước Metal, trong đó trục Y hướng xuống và trục Z hướng ra khỏi màn hình. Lưu ý rằng hướng trục Y là hướng xuống trong toạ độ bộ đệm khung, toạ độ khung nhìn và toạ độ mảnh/pixel. Trong không gian đoạn video, hướng của trục Y vẫn là hướng lên trên như trong WebGL.
Lời cảm ơn
Cảm ơn Corentin Wallez, Gregg Tavares, Stephen White, Ken Russell và Rachel Andrew đã xem xét bài viết này.
Bạn cũng nên truy cập WebGPUFundamentals.org để tìm hiểu kỹ về sự khác biệt giữa WebGPU và WebGL.