7 điểm bởi GN⁺ 2025-12-17 | 1 bình luận | Chia sẻ qua WhatsApp
  • Trong 10 năm qua, các graphics API cấp thấp như DirectX 12, Vulkan, Metal đã nâng hiệu năng GPU lên, nhưng độ phức tạp và chi phí bảo trì cũng tăng vọt
  • GPU hiện đại hỗ trợ hệ phân cấp cache hoàn chỉnh, con trỏ 64-bit, tài nguyên bindless, khiến các đối tượng trạng thái và mô hình binding phức tạp trước đây trở nên không còn cần thiết
  • Thiết kế được đề xuất sử dụng truy cập bộ nhớ dựa trên con trỏ C/C++một con trỏ gốc 64-bit duy nhất để đơn giản hóa mạnh mẽ pipeline dựng hình
  • Đề xuất này loại bỏ bùng nổ PSO, resource barrier, API binding phức tạp và đưa ra một cấu trúc kết nối trực tiếp giữa bộ nhớ GPU với ngôn ngữ shader
  • Cách tiếp cận này là API thế hệ tiếp theo được tối ưu cho kiến trúc GPU hiện đại, đồng thời gợi ra hướng đi mà DirectX 13 hay Vulkan 2.0 nên theo đuổi

Sự thay đổi của graphics API cấp thấp

  • Kiến trúc AMD GCN trên Xbox One và PS4 năm 2013 đã trở thành tiêu chuẩn cho phát triển game AAA, kéo theo sự xuất hiện của các API cấp thấp như Mantle, DirectX 12, Vulkan, Metal
    • Nói cách khác, chúng được thiết kế dựa trên kiến trúc GPU vào khoảng năm 2013
  • DirectX 11/OpenGL trước đây có giới hạn do dựng hình đơn luồng và overhead driver cao
  • Các API này đã giảm chi phí draw call bằng đối tượng pipeline được biên dịch trước (PSO), nhưng vì không khớp với cấu trúc engine nên độ phức tạp tăng lên
  • Kết quả là bên trong engine lại xuất hiện thêm một “lớp driver cấp thấp” khác, làm vai trò của lập trình viên đồ họa bị phân mảnh hơn

Bối cảnh lịch sử: vì sao mọi thứ lại trở nên phức tạp

  • GPU đời đầu có cấu trúc xoay quanh bộ nhớ tách biệt và pipeline chức năng cố định
  • OpenGL và DirectX áp dụng thiết kế dựa trên trạng thái và đối tượng để trừu tượng hóa sự đa dạng phần cứng
  • Ngay cả đến DirectX 11, texture và buffer vẫn được quản lý bằng descriptor opaque
  • Cách thiết kế này sau đó vẫn tiếp tục được giữ lại theo quán tính trong các API về sau

Sự lệch pha giữa GPU hiện đại và API

  • GPU hiện nay hỗ trợ hệ phân cấp cache nhất quán, PCIe ReBAR, con trỏ 64-bit, texture bindless
  • Có thể xây dựng cấu trúc CPU ghi trực tiếp vào bộ nhớ GPU và GPU đọc ngay lập tức
  • Trong môi trường như vậy, các cấu trúc như PSO, descriptor set, bảng binding trở nên không cần thiết
  • Do vấn đề bùng nổ cache PSO, có thể cần tới hàng trăm GB cache, gây ra độ trễ tải và hiện tượng giật khựng
  • API mới có thể loại bỏ những cấu trúc lỗi thời này và chuyển sang cách truy cập đơn giản dựa trên con trỏ

Đơn giản hóa quản lý bộ nhớ GPU

  • Vulkan/DirectX 12 hiện tại yêu cầu tra cứu khả năng tương thích với heap sau khi tạo tài nguyên, gây kém hiệu quả
  • Cách tiếp cận được đề xuất cấp phát trực tiếp bộ nhớ GPU bằng API đơn giản dạng gpuMalloc/gpuFree
    • CPU có thể trực tiếp map bộ nhớ GPU để khởi tạo
    • Dữ liệu lớn được truyền bằng lệnh copy để thực hiện nén DCC và xử lý swizzle
  • Phân biệt địa chỉ map phía CPU với địa chỉ GPU, và chuyển đổi bằng gpuHostToDevicePointer

Hiện đại hóa dữ liệu và ngôn ngữ shader

  • Sử dụng ngôn ngữ shader dựa trên con trỏ C/C++ như CUDA, Metal, OpenCL
  • Có thể truy cập bộ nhớ hiệu quả bằng wide load ở cấp độ struct (128-bit trở lên)
  • ByteAddressBuffer hay texel buffer của DirectX không còn là lựa chọn tối ưu
  • GLSL/HLSL không hỗ trợ con trỏ nên thiếu hệ sinh thái thư viện shader có thể tái sử dụng; trong khi đó CUDA đã phát triển được hệ thư viện phong phú

Root argument và cấu trúc dữ liệu

  • Kernel GPU nhận đầu vào là một con trỏ 64-bit duy nhất rồi ép kiểu thành struct
  • CPU và GPU dùng chung cùng header C/C++ để đảm bảo tính nhất quán của cấu trúc dữ liệu
  • Dùng từ khóa const/restrict để thúc đẩy tối ưu hóa của compiler, đồng thời bỏ sự phân chia UBO/SSBO không cần thiết
  • Tận dụng nạp trước scalar registertối ưu hóa dynamic uniform của GPU hiện đại

Đơn giản hóa binding texture

  • Quản lý toàn bộ texture bằng mảng descriptor 256-bit (heap), cho phép cả CPU và GPU ghi trực tiếp
  • Hỗ trợ lấy mẫu texture non-uniform bằng truy cập dựa trên chỉ số 32-bit
  • Đơn giản hơn descriptor heap của DirectX 12 SM 6.6 và tương tự Vulkan VK_EXT_descriptor_buffer
  • Việc tạo texture, upload và sampling đều được thống nhất trên nền con trỏ bộ nhớ GPU

Shader pipeline và hằng số

  • Việc tạo pipeline chỉ đơn giản là nạp shader IR rồi gọi gpuCreatePipeline
  • Không cần root signature, descriptor set hay định nghĩa binding
  • Thay thế shader specialization constant bằng hằng số tĩnh (dựa trên struct) để giảm vấn đề bùng nổ tổ hợp PSO
  • Struct hằng số có thể chứa cả con trỏ GPU, cho phép hard-code trực tiếp địa chỉ runtime

Đơn giản hóa barrier và đồng bộ

  • Danh sách barrier theo từng tài nguyên của API hiện tại không khớp với cấu trúc GPU hiện đại
  • Mô hình được đề xuất chỉ dùng cờ bitfield theo queue/stage
  • Đơn giản hóa thành dạng gpuBarrier(before, after, hazard), không cần theo dõi tài nguyên
  • Triển khai đồng bộ GPU→GPU tương tự timeline semaphore bằng các lệnh gpuSignalAfter / gpuWaitBefore

Command buffer và dựng hình

  • Chỉ dùng command buffer dùng một lần (transient), loại bỏ mô hình tái sử dụng phức tạp của Vulkan
  • Thiết lập render target và clear bằng gpuBeginRenderPass / gpuEndRenderPass
  • Không có barrier tự động giữa các render pass, nhờ đó có thể tối ưu dựng hình song song và depth pre-pass

Đơn giản hóa raster pipeline

  • Vertex/pixel shader truy cập dữ liệu dựa trên con trỏ, loại bỏ API binding
  • Tách GpuDepthStencilState, GpuBlendState ra khỏi PSO để giảm số lượng tổ hợp
  • GPU di động hỗ trợ programmable blending bằng framebuffer fetch intrinsic
  • PSO chỉ còn chứa trạng thái tối thiểu như topology, format, số lượng sample...

Indirect draw và dựng hình do GPU điều khiển

  • Mọi đối số (data, arguments) đều được truyền bằng con trỏ GPU
  • Hỗ trợ multi-draw bằng gpuDrawIndexedInstancedIndirectMulti
  • GPU có thể tự tạo dữ liệu root và đối số draw, hiện thực GPU-driven rendering hoàn chỉnh

Tooling và khả năng tương thích

  • Cấu trúc dựa trên con trỏ có thể được truy vết qua thông tin symbol như debugger của CUDA/Metal
  • Được bảo vệ bằng bộ nhớ ảo nên không có vấn đề bảo mật; truy cập sai sẽ gây page fault
  • Tương tự các trường hợp MoltenVK, Proton, API DirectX/Vulkan/Metal hiện có có thể được hỗ trợ qua lớp chuyển đổi

Yêu cầu tối thiểu và kết luận

  • Nvidia Turing(2018), AMD RDNA1(2019), Intel Xe1(2022), Apple M1(2020) đều hỗ trợ các tính năng được đề xuất
  • GPU ngày nay đã chuyển sang kiến trúc bindless, con trỏ 64-bit, cache nhất quán
  • Chỉ có API vẫn đang bị trói buộc bởi những lớp trừu tượng của quá khứ
  • API mới sẽ đơn giản hơn DirectX 11, nhanh hơn Vulkan và linh hoạt hơn Metal
  • Vulkan 2.0 / DirectX 13 thế hệ tiếp theo cần chuyển sang thiết kế bindless hoàn toàn, đồng thời mở rộng hệ sinh thái bằng ngôn ngữ shader dựa trên con trỏ C/C++ thay cho HLSL/GLSL

1 bình luận

 
GN⁺ 2025-12-17
Ý kiến trên Hacker News
  • Đây là một bài viết rất xuất sắc, cho thấy rõ những phần không cần thiết của VulkanDX12
    Dạo này DX12 thậm chí còn không hỗ trợ cả con trỏ buffer, nên có cảm giác gần như bị bỏ mặc, còn Vulkan thì cũng không được dọn dẹp thành 2.0 nên có rất nhiều driver triển khai extension không tử tế
    Nếu tồn tại một API mới như vậy, có lẽ OpenGL có thể được giả lập trên đó nhanh hơn rất nhiều, và những thứ như SDL3 GPU cũng có thể đạt mức cải thiện hiệu năng gấp 3~4 lần

    • Tình trạng tài liệu DirectX hiện tại quá tệ
      Sách của Frank Luna cũng không đề cập hết các tính năng mới nhất, và phải lục tung Learn, các mẫu trên GitHub, cùng tài liệu tham chiếu
      Vulkan cũng phức tạp tương tự, và ngay cả khi 2.0 ra mắt thì vẫn đáng nghi liệu trên các nền tảng quan trọng như Android người ta sẽ thực sự dùng nó như thế nào
    • Tôi nghĩ tất cả chuyện này có lẽ là vì yêu cầu PCI Resizable BAR
      Ngoài Intel Arc ra thì phần lớn GPU vẫn chạy được dù không có reBAR, nhưng có vẻ Microsoft hoặc Intel sẽ phải ép buộc điều này ở UEFI thì mới có thể dùng ổn định các tính năng như bindless texture
      Tuy nhiên nếu vậy thì sẽ xuất hiện ngưỡng phần cứng tối thiểu được hỗ trợ, và trên các bo mạch chủ trước năm 2020 thì mức hỗ trợ rất chắp vá
  • Bài viết đã thiếu mất động lực cốt lõi
    Theo chỉ mục blog, tinh thần của nó là: “Trong 10 năm qua, độ phức tạp của graphics API và ngôn ngữ shader đã tăng vọt, và giờ cần đơn giản hóa tầng trừu tượng để nâng cao hiệu quả phát triển, hiệu năng, đồng thời chuẩn bị cho các workload GPU trong tương lai”

    • Điều này khá giống với lý do NVMe ra đời
      Ban đầu SSD tái sử dụng giao diện IDE/SATA, nhưng để đạt hiệu năng thật sự thì phải từ bỏ các giả định của đĩa quay và tạo ra một phương thức truyền mới
      Có vẻ đây là một phép so sánh rằng graphics API cũng đã đến lúc phải bỏ đi những ràng buộc legacy như thế
  • Tôi có thể hơi thiên vị vì đã theo dõi công việc của Sebastian Aaltonen từ lâu, nhưng bài này thực sự rất xuất sắc
    Tôi nghĩ hướng đi trong tương lai là quay trở lại software rendering
    Chỉ khác là lần này các thuật toán và cấu trúc dữ liệu đó sẽ được tăng tốc bằng phần cứng
    Trong ngành VFX, xu hướng này đã diễn ra rồi, và việc OTOY port OctaneRender sang nền CUDA vào khoảng 5 năm trước cũng là một ví dụ

    • Bên trong GPU có rất nhiều fixed-function hardware, nên nếu bỏ đi thì hiệu năng sẽ giảm mạnh
      Các loại shader đóng vai trò lấp đầy khoảng trống giữa các pipeline này, nên việc phần mềm hóa hoàn toàn là không thực tế
    • Thực ra một phần thay đổi này đã diễn ra rồi
      Ví dụ, Nanite của Unreal Engine dùng một software rasterizer chạy bằng compute shader của GPU khi xử lý các tam giác nhỏ
  • Phần chi tiết của bài viết thật ấn tượng
    Tôi chỉ hiểu được một phần, nhưng có vẻ nó sẽ trở thành tài liệu tham khảo cho thiết kế graphics API trong tương lai
    Với đa số game thủ, Vulkan/DX12 không mang lại lợi ích lớn, và nhiều game đã khổ sở vì vấn đề PSO
    Vulkan đang được cải thiện, nhưng WebGPU đã kế thừa nguyên các ràng buộc từ thiết kế Vulkan ban đầu
    Trong bối cảnh phần cứng tiến hóa quá nhanh, có lẽ việc đi quá sâu xuống API mức thấp là một sai lầm
    Thay vào đó, cách tiếp cận tập trung vào điện toán đa dụng như CUDA có khi lại là hướng đi tốt hơn

  • Tôi thấy nhớ Mantle
    Dù cũng có nhược điểm, nhưng nó cho cảm giác được chạm tay trực tiếp vào phần cứng, và thời kỳ phát triển cho Xbox 360 là lúc tôi thấy vui nhất

    • Graphics API của Switch cũng tuyệt vời theo cách tương tự
      Nó do Nvidia và Nintendo thiết kế, và tôi thấy đó là API trực quan nhất trong số các console
  • Đọc bài này xong tôi có cảm giác như vừa chứng kiến một khoảnh khắc mang tính lịch sử

  • Nó làm tôi nhớ đến Google Toucan, có vẻ là một dự án liên quan

  • Bài này gợi lại cho tôi rất nhiều ký ức cũ
    Một số yếu tố bổ sung mà các nhà thiết kế API phải cân nhắc là

    • GPU virtualization — tính năng cho phép nhiều ứng dụng cùng chia sẻ tài nguyên GPU (ví dụ: D3D residency API)
    • hành vi không xác định (Undefined Behavior) — nếu ứng dụng vô tình phụ thuộc vào nó thì việc port sang API mới sẽ trở nên khó khăn
  • Tôi tự hỏi vì sao Microsoft không ra một phiên bản DirectX mới
    DirectX Ultimate hay 12.2 thực ra về bản chất vẫn là DX12
    Có phải do ảnh hưởng của middleware như Unreal Engine làm giảm tầm quan trọng của API riêng, hay là EPIC nên là bên đề xuất API mới?

    • Những thảo luận kiểu này chủ yếu chỉ sôi nổi trong cộng đồng FOSS
      Các nhà phát triển game thực tế thì tạo RHI (Rendering Hardware Interface) để tập trung làm game
      Ray tracingmesh shader là những đổi mới lớn nhất, nhưng vẫn chưa được tận dụng nhiều nên có vẻ mọi thứ chưa tiến xa thêm
    • Ở mức độ nào đó thì cả hai đều đúng
      Sự tập trung hóa của các engine như Unreal, Unity đã làm giảm sự quan tâm tới đổi mới API, và chỉ phía GPU là tiếp tục phát triển
      API phía CPU vẫn chỉ ở mức map buffer đơn giản
      Có lẽ sẽ cần một thay đổi phần cứng mới thì mới có tiến triển, giống như thời tessellation shader xuất hiện trước đây
  • Tôi tò mò liệu Valve có khả năng tự làm một graphics API cho SteamOS hay không

    • Thực ra độ phức tạp của Vulkan cũng có phần trách nhiệm của Valve
      Tôi từng nghe rằng trong giai đoạn phát triển ban đầu của Vulkan, Valve là một trong những bên dẫn dắt chủ chốt