- Từ OBS Studio 32.0.0 cho macOS, một backend trình kết xuất dựa trên Apple Metal đã được bổ sung ở mức thử nghiệm, nhằm cải thiện hiệu năng và hiệu quả so với OpenGL trước đây
- Metal là API được thiết kế để có overhead thấp và phản ánh kiến trúc GPU hiện đại, vì vậy OBS đã phải sửa đổi tận gốc cách tương tác với GPU để hỗ trợ nó
- Do trình kết xuất hiện có của OBS được xây dựng theo cấu trúc xoay quanh Direct3D, backend Metal đã phải thực hiện khối lượng lớn công việc tương thích ở các phần như chuyển đổi shader và quản lý tài nguyên
- Đặc biệt, phần triển khai bao gồm việc chuyển đổi shader HLSL sang MSL theo thời gian thực và mô phỏng hành vi
map/unmap của Direct3D bên trong Metal
- Backend Metal vẫn đang ở giai đoạn “thử nghiệm”, nhưng với hiệu năng nhanh hơn OpenGL, cấu trúc mã an toàn dựa trên Swift và hỗ trợ preview EDR, đây là một bước ngoặt quan trọng giúp cải thiện môi trường phát triển trên macOS
Tổng quan về việc đưa trình kết xuất Metal vào
- Từ OBS Studio 32.0.0, trên macOS đã cung cấp thử nghiệm trình kết xuất dựa trên API đồ họa Metal
- Đây là lựa chọn thay thế cho backend OpenGL hiện tại, với mục tiêu nâng cao hiệu năng và hiệu quả
- Metal là một API hiện đại làm thay đổi tận gốc cách tương tác với GPU, và OBS đã điều chỉnh cấu trúc nội bộ để phù hợp với điều này
- Backend Metal được gắn nhãn “Experimental” và hiện có một số vấn đề, giới hạn đã biết
- Trình kết xuất OpenGL vẫn được giữ làm mặc định, và người dùng có thể tự thử phiên bản Metal
- Nhóm phát triển khuyến khích phản hồi và Pull Request từ các lập trình viên có kinh nghiệm với Metal
Bối cảnh và triết lý thiết kế của Metal
- Apple lần đầu giới thiệu Metal cho iPhone vào năm 2014, và mở rộng sang Mac vào năm 2015
- Khi đó, Metal là một trong những API đồ họa thế hệ mới đầu tiên hỗ trợ cả GPU Intel, AMD và NVIDIA
- Metal kết hợp các khái niệm từ Mantle của AMD cùng OpenGL và Direct3D trước đó, nhưng được thiết kế lại với việc loại bỏ các yếu tố legacy
- Đây là API dựa trên Objective-C và Swift, mang lại cấu trúc quen thuộc cho lập trình viên iOS và macOS
- Trong Xcode, Metal hỗ trợ tích hợp gỡ lỗi shader và phân tích GPU
Khác biệt trong thiết kế API và sự thích nghi của trình kết xuất OBS
- OpenGL và Direct3D trước đây tự động xử lý quản lý tài nguyên và đồng bộ hóa, nhưng
các API hiện đại như Metal yêu cầu lập trình viên tự quản lý trực tiếp
- Các API mới xem GPU như một thiết bị xử lý dựa trên hàng đợi lệnh song song, đồng thời quản lý trạng thái pipeline bằng các đối tượng bất biến
- Trình kết xuất hiện tại của OBS được thiết kế theo cách của Direct3D, nên
để hỗ trợ Metal, OBS đã triển khai một lớp tương thích ở cấp backend
Cấu trúc trình kết xuất của OBS và vấn đề tương thích với Metal
- OBS sử dụng các backend Direct3D (Windows) và OpenGL (Linux/macOS) theo từng nền tảng
- Phần lõi của trình kết xuất độc lập với API, nhưng vẫn tồn tại một số giả định xoay quanh Direct3D
- Các ràng buộc chính
- Shader được viết dựa trên HLSL, nên cần chuyển đổi khi chạy
- Có các yếu tố như sử dụng biến toàn cục, giả định thực thi tuần tự và cách xử lý texture kiểu Direct3D
- Kết xuất preview phụ thuộc vào ‘discard model’ của DXGI
Chuyển đổi shader (Transpiling Shaders)
- Các file hiệu ứng của OBS được viết bằng HLSL và được chuyển đổi theo từng API tương ứng
- Để hỗ trợ Metal, một bộ chuyển đổi HLSL → MSL đã được thêm vào
- Những khác biệt chính
- MSL yêu cầu tách riêng struct đầu vào/đầu ra và không hỗ trợ biến toàn cục
- Toàn bộ dữ liệu uniform phải được truyền qua GPU buffer, và cần được truyền tường minh dưới dạng tham số hàm
- Khi gọi hàm, việc khớp kiểu và kiểm tra chữ ký hàm được thực hiện rất nghiêm ngặt
- Bộ chuyển đổi sẽ viết lại một phần mã shader tại runtime để phù hợp với quy tắc của MSL
- Ví dụ, biến
uniform trong HLSL được chuyển thành constant buffer trong MSL
- Logic chuyển kiểu như
int3 → uint2 + uint cũng được tự động chèn vào
Mô phỏng hành vi của Direct3D
- Trình kết xuất OBS được thiết kế dựa trên giả định về hành vi
map/unmap của Direct3D
- Vì Metal không cung cấp cơ chế đồng bộ tự động như vậy, nên backend phải tự triển khai trực tiếp
- Cách backend Metal xử lý
- Khi ghi, tạo GPU buffer và chia sẻ trực tiếp với bộ nhớ CPU
- Khi
unmap, lên lịch lệnh blit của GPU để sao chép sang texture
- Khi đọc, cũng chia sẻ GPU buffer nhưng tránh xung đột bằng đồng bộ hóa tường minh
- Kết quả là các chức năng theo dõi tài nguyên và đồng bộ hóa của Direct3D được tái hiện bên trong Metal
Vấn đề kết xuất preview và giải pháp tạm thời
- Metal Layer trên macOS, khác với DXGI, không cho phép ứng dụng tùy ý hiển thị frame
- Hệ thống sẽ điều khiển tốc độ khung hình theo ProMotion và chế độ tiết kiệm điện
- Do vòng lặp kết xuất riêng của OBS không khớp với chu kỳ hiển thị của macOS, nên phát sinh độ trễ preview
- Giải pháp tạm thời
- OBS trước tiên kết xuất vào texture ảo, sau đó một luồng riêng sẽ sao chép nó sang surface hiển thị
- Quá trình này cần đồng bộ GPU và có khả năng xảy ra lệch khung hình
- Từ macOS 14 trở đi, dự kiến sẽ có thêm thách thức do bộ hẹn giờ độc lập theo từng cửa sổ
Chi phí ẩn của các API đồ họa hiện đại
- Việc phát triển backend Metal đã trải qua nhiều tháng nghiên cứu và lặp lại thiết kế
- Điều này cho thấy rõ vì sao quá trình chuyển từ OpenGL sang Vulkan hoặc từ D3D11 sang D3D12 có thể làm suy giảm hiệu năng
- Với các API hiện đại, những việc trước đây do driver đảm nhiệm nay ứng dụng phải trực tiếp thực hiện
- Điều đó đòi hỏi hiểu biết sâu về nguyên lý hoạt động của GPU và sự phụ thuộc giữa các lệnh
- Dù backend Metal có tái đưa vào một phần overhead, nó vẫn mang lại các lợi ích sau
- Hiệu năng tương đương hoặc tốt hơn OpenGL
- Khả năng phân tích mạnh mẽ như gỡ lỗi shader và texture
- Cấu trúc mã an toàn dựa trên Swift
- Hỗ trợ preview EDR giúp xử lý video chất lượng cao
- Nhờ các tính năng phân tích tích hợp trong Xcode, hiệu quả bảo trì OBS trên macOS được cải thiện, và nhóm phát triển đang kêu gọi phản hồi từ lập trình viên để trong tương lai chuyển Metal thành trình kết xuất mặc định
1 bình luận
Ý kiến trên Hacker News
Bài viết thực sự rất hay. Phần giải thích về cách xử lý shader thật sự gây ấn tượng
Tôi tự hỏi liệu để shader của plugin bên thứ ba chạy được trên nhiều backend thì có thực sự phải đi qua quy trình như vậy không, hay là mọi thứ trở nên như thế vì duy trì khả năng tương thích ngược
Việc nói với nhà phát triển bên ngoài rằng “hãy tự viết cho từng ngôn ngữ shader” có thể là lựa chọn dễ dàng với đội ngũ cốt lõi, nhưng trên thực tế thì không hề lý tưởng
Ai cũng nghĩ nó kém hiệu quả, nhưng thực tế là không có lựa chọn thay thế
Tiêu đề bài viết đang che mất trọng tâm
Nó nên đổi thành kiểu như “OBS Studio giới thiệu renderer mới: quá trình áp dụng Metal”
Điều này cho thấy rất rõ cái giá của việc Apple tạo ra API riêng để bảo vệ hệ sinh thái thay vì dùng Vulkan
OBS Studio đã thêm hỗ trợ Vulkan vào tháng 3 năm 2020, ở phiên bản 25.0. Đến nay đã 5 năm rưỡi rồi
Trong môi trường nhúng, OpenGL ES vẫn là trung tâm
Tôi không phải chuyên gia về chủ đề này. Tôi chỉ hiểu được chắc khoảng 5% những gì đã đọc, nhưng tôi vẫn muốn có thêm nhiều bài viết giải thích chi tiết kỹ thuật như thế này
Những bài chỉ đơn thuần là thông báo thì nghe giống marketing hơn
Cá nhân tôi còn mong chờ hỗ trợ VST3 sắp tới hơn, nhưng tin này cũng rất đáng mừng
Dù sao thì nó vẫn dễ hơn rất nhiều so với việc cấu hình mã hóa phần cứng trên Rockchip SoC
Tôi thấy thú vị với cách giải thích rằng Metal đã đẩy cách tiếp cận hướng đối tượng của Direct3D đi xa thêm một bước, rồi kết hợp với kiểu thiết kế API “nhiều lời” của Objective-C và Swift
Thật ngạc nhiên khi một API đồ họa 3D cấp hệ điều hành lại có thể được xây dựng theo kiểu dựa trên ngôn ngữ động như vậy
Tôi nghĩ điều này là nhờ tối ưu hóa của
objc_msgSend()Vulkan/Metal/DirectX 12 truyền nhiều lệnh trong command buffer thay vì gọi từng lệnh riêng lẻ
Hồi đầu những năm 2000 đã có sách về việc dùng Direct3D với C#, và nó đã thay đổi nhận thức rằng đồ họa hiệu năng cao vẫn có thể làm được trong ngôn ngữ có GC
Cốt lõi là giảm overhead runtime bằng cấu trúc xử lý theo lô tham chiếu đến các buffer được cấp phát sẵn
Sau Cocoa, phần lớn được viết bằng một tập con C++ bị giới hạn (ví dụ: IOKit)
Tôi hy vọng các API GPU hiện đại chỉ là một giai đoạn chuyển tiếp để đi đến thứ gì đó đơn giản hơn
Tôi vừa yêu vừa ghét OpenGL, nhưng sau khi dùng các API mới thì lại thấy nhớ sự đơn giản của OpenGL
Tôi tò mò không biết Metal có cải thiện hiệu năng cả trên Intel Mac đời cũ hay chỉ là tối ưu hóa dành riêng cho dòng M
Nhưng Metal 3 vẫn còn hỗ trợ trên nhiều máy Intel Mac, nên không rõ vì sao lại giới hạn như vậy
Tôi đang nghĩ đến việc dựng một bộ máy stream bằng Mac Mini
Tôi muốn biết liệu với mức cải thiện hiệu năng này thì nó đã đủ khả thi chưa
Nếu là game arcade 2D hay màn hình phát triển phần mềm thì không vấn đề gì
Nếu là game AAA mới thì tốt hơn nên nhận màn hình từ PC qua capture card
Khoảng năm 2017 thì stream bằng macOS còn khá vất vả, nhưng giờ nếu là dòng M thì đã đủ dùng rồi
Với cải tiến lần này, tôi kỳ vọng hiệu suất sử dụng tài nguyên sẽ còn tốt hơn nữa
Tôi mong Apple đầu tư thêm tài nguyên để tăng số câu chuyện thành công bên ngoài của Metal
Ngoài nội bộ Apple ra, Metal vẫn chưa có nhiều thành công lớn