[Unity Series 6] Tối ưu hiệu năng Ứng dụng game Unity - Tối ưu GPU (tiếp)

Trong phần tiếp theo của Series tối ưu ứng dụng game Unity mình sẽ tiếp tục các phương pháp về 2 vấn đề còn lại là Memory Bandwidth và Vertex Processing.

6 min read
Bởi Datbq
[Unity Series 6] Tối ưu hiệu năng Ứng dụng game Unity - Tối ưu GPU (tiếp)

[Unity Series 5] Tối ưu hiệu năng Ứng dụng game Unity - Tối ưu GPU

Trong phần trước, mình đã giới thiệu cụ thể các phương pháp tối ưu GPU khi gặp vấn đề về Fill rate. Trong phần này mình sẽ tiếp tục các phương pháp về 2 vấn đề còn lại là Memory Bandwidth và Vertex Processing.

Memory Bandwidth

Memory Bandwidth (Băng thông bộ nhớ) đề cập đến tỉ lệ đọc và ghi của GPU vào bộ nhớ chuyên dụng của nó. Nếu chúng ta gặp vấn đề về Memory Bandwidth, điều này có nghĩa là chúng ta đang sử dụng texture quá lớn khiến GPU bound.
Để kiểm tra Memory Bandwidth, bạn có thể thực hiện những bước sau:

  • Profile game và note lại GPU time.
  • Thử giảm Texure Quality trong Quality Settings.
  • Profile lại game của bạn và so sánh GPU time đã được note. Nếu hiệu năng của game được cải thiện thì có lẽ Memory Bandwidth là vấn đề của bạn.
    topic6_1
    Để tối ưu Memory Bandwidth, công việc chúng ta cần làm là giảm bộ nhớ sử dụng cho texture. Có một vài cách thực hiện điều này như sau:
    Texture compression (nén texture) là một kĩ thuật cho phép giảm đáng kể kích thước texture trên cả disk và memory. Có nhiều loại định dạng nén texture khác nhau đã được cài đặt sẵn trong unity và mỗi texture sẽ có các cài đặt riêng biệt. Theo nguyên tắc chung, chúng ta nên sử dụng các hình thức nén Texture bất cứ khi nào có thể. Tuy nhiên, bạn cũng nên thử nghiệm các dạng nén để tìm ra lựa chọn phù hợp nhất cho texture của mình.
    topic6_2
    Mipmaps là phiên bản có độ phân giải thấp của texture mà Unity có thể sử dụng cho các đối tượng ở xa. Nếu trong Scene của bạn có những đối tượng cách xa Camera, bạn có thể sử dụng mipmap để giảm bớt các vấn đề về Memory Bandwidth.
    topic6_3
    Mipmaps Draw Mode sẽ hiển thị kích thước lý tưởng của texture sử dụng một mã màu: màu red chỉ ra rằng texture nào lớn hơn cần thiết và màu blue thể hiện texture nào có thể lớn hơn nữa.
    topic6_4

Vertex Processing

Vertex Processing đề cập đến các công việc mà GPU phải làm để render mỗi Vertex (đỉnh) trong một mesh. Phí tổn của hoạt động này bị tác động bởi 2 yếu tố: số đỉnh phải được render và số lượng các tính toán được thực hiện trên mỗi đỉnh.
Nếu game của bạn gặp GPU bound và Fill rate cũng như Memory Bandwidth không phải là vấn đề, vậy bạn nên tìm hiểu cách tối ưu Vertex Processing. Cách đơn giản nhất để tối ưu Vertex Processing là giảm số lượng đỉnh mà GPU phải xử lý, sẽ cải thiện hiệu năng của ứng dụng.
Có một vài cách tiếp cận mà chúng ta có thể xem xét đến để giúp chúng ta giảm số đỉnh hoặc số tính toán được thực hiện trên mỗi đỉnh như sau:

  • Đầu tiên, bạn nên tập trung vào việc giảm những mesh phức tạp không cần thiết. Nếu bạn đang sử dụng các mesh có mức độ chi tiết mà không thể nhìn thấy trong game, hoặc các mesh có quá nhiều đỉnh không cần thiết do sai sót trong việc tạo ra chúng, thì đây chính là các vấn đề làm lãng phí GPU. Cách đơn giản nhất để giảm chi phí cho việc xử lý đỉnh là tạo ra các mesh với số đỉnh được giảm thiểu hết mức có thể bằng các phần mềm xử lý đồ hoạ 3D.
  • Bạn cũng có thể thử nghiệm với một kĩ thuật được gọi là normal mapping. Normal Map là một hình ảnh được thêm vào 3D model làm tăng độ chi tiết của model, bao bọc xung quanh những model 3D mà bạn có thể chỉnh sửa một số thuộc tính như màu sắc, độ trong suốt, phản chiếu, và độ chi tiết. Nó được sử dụng để tăng độ chi tiết cho các low-poly model (model có độ phân giải thấp) trong khi vẫn giữ được dung lượng thấp.
    BumpMapLowAndHighBumpiness
    Mặc dù sử dụng Normal mapping sẽ có một ít phí tổn GPU, tuy nhiên trong hầu hết trường hợp nó sẽ làm cải thiện hiệu năng.
    BumpMapPutIntoShader
  • Nếu mesh trong game của bạn không sử dụng normal mapping, bạn có thể vô hiệu hoá việc sử dụng Vertex Tangents của mesh ở trong phần Import Setting. Điều này sẽ làm giảm lượng dữ liệu được gửi đến GPU cho mỗi đỉnh.
    topic6_6
  • Một phương pháp khác cực kỳ phổ biến trong các game mà có lẽ các bạn đã gặp rất nhiều lần là Level of detail (LOD). LOD là kĩ thuật tối ưu hoá mesh bằng cách giảm bớt độ phức tạp của mesh ở những object cách xa Camera. Điều này sẽ làm giảm số đỉnh mà GPU phải render mà không ảnh hưởng đến chất lượng của trò chơi. Một ví dụ để bạn dễ hình dung kĩ thuật này là trong một game khá nổi bây giờ Rules of Survival, khi bạn nhìn những toà nhà đằng xa sẽ thấy rất mờ, nhưng khi bạn đến gần hoặc dùng ngắm sẽ thấy toà nhà trở nên rất chi tiết.
    InspectorLODGroup
  • Vertex Shaders là một phần của shader code, chỉ thị GPU làm thế nào để vẽ mỗi đỉnh. Nếu game của bạn sử dụng Shader của Unity, bạn nên thử nghiệm việc sử dụng các shader đơn giản và được tối ưu để tăng hiệu năng của ứng dụng (mobile shader,…)

KẾT LUẬN

Vậy là trong 6 phần thuộc Series tối ưu hoá ứng dụng game Unity, chắc hẳn bạn đã định hình được những bước cần phải thực hiện để tối ưu ứng dụng của mình. Tối ưu hiệu năng thực tế là những công việc thường ngày của bạn, cần phải làm thường xuyên. Bạn nên tránh việc chỉ tối ưu sau khi đã hoàn thành sơ bộ ứng dụng, như vậy sẽ làm tăng độ phức tạp lên rất nhiều. Trong các phần sau của Series, mình sẽ đi vào các phương pháp tối ưu như tối ưu Script, tối ưu UI, tối ưu Model,.. Hy vọng các bạn sẽ tiếp tục ủng hộ Series này.