Sử dụng instaging cho mọi thứ?


16

Instance cải thiện hiệu suất (đáng kể) khi hiển thị nhiều bản sao (hunders? Hàng ngàn?) Của cùng một lưới. Nhưng nó có bao nhiêu chi phí khi kết xuất chính xác một bản sao với một lệnh gọi? Nó sẽ là một ý tưởng tốt hay xấu khi sử dụng instaging cho tất cả các hình học được kết xuất bởi động cơ?

Chỉnh sửa: Giả sử chúng tôi đang tạo một trò chơi FPS. Hầu hết các đối tượng chỉ có một ví dụ: dao, súng, súng máy, tòa nhà và tháp radio. Nhưng cũng có một số đối tượng có nhiều trường hợp: cây (ví dụ 3 loại cây với hàng trăm trường hợp), cỏ và vân vân ... Ý tôi là: thay vì hiển thị các đối tượng một cách theo cách và cây "truyền thống" và cỏ sử dụng inst instaging, chúng tôi kết xuất tất cả chúng bằng inst instaging. Vì vậy, tháp radio của chúng tôi chỉ có một thể hiện (có thông tin chúng tôi lưu trữ trong bộ đệm dữ liệu cá thể) và chúng tôi kết xuất tháp đó bằng cách sử dụng một số loại DrawInstanced()cuộc gọi với số lượng cá thể bằng nhau 1. Tương tự với tất cả các đối tượng khác (tất nhiên, cây và cỏ có nhiều trường hợp).

Vì vậy, câu hỏi của tôi là: có phải là một ý tưởng tồi khi vẽ một trường hợp duy nhất của một đối tượng bằng cách sử dụng không? Liệu instaging có quá nhiều chi phí hoạt động (bộ nhớ và hiệu năng) hay nó theo bất kỳ cách nào không mong muốn để hiển thị các đối tượng đơn lẻ?

Câu trả lời:


19

Trong D3D9 với XPDM, bạn gần như chắc chắn muốn ví dụ bất cứ nơi nào có thể. Vẽ cuộc gọi trên cao chỉ là rất cao mà nó có ý nghĩa. Trong kịch bản đó, điểm giao nhau có thể thấp đến 2 hoặc 3 trường hợp.

Nếu bạn chỉ có một thể hiện của một lưới nhất định, thì trên bề mặt có vẻ hấp dẫn khi vẽ nó không có bản năng. Tuy nhiên, hãy nhìn vào những gì liên quan:

  • Bạn cần chuyển từ tải dữ liệu sang bộ đệm theo từng trường hợp để tải lên các hằng số shader.
  • Bạn cần giữ hai bản sao của shader đỉnh của bạn: một cho bản năng và một bản không bản năng.
  • Bạn cần giữ hai bản sao mã kết xuất của mình: tương tự.
  • Bạn cần phải chuyển shader.
  • Bạn cần chuyển đổi định dạng đỉnh.
  • Bạn có thể cần phải chuyển đổi bộ đệm đỉnh.
  • Và sau đó, bạn cần phải làm lại từ đầu nếu bạn quay trở lại bản vẽ có bản năng cho nhóm mắt lưới tiếp theo.

Ngay cả khi bạn chỉ có một lưới duy nhất (như mô hình súng trong FPS), vẫn có trường hợp việc kích hoạt là hữu ích. Giả sử bạn đang thực hiện tích lũy ánh sáng nhiều lần trong trình kết xuất chuyển tiếp và với phần mở rộng z. Thay vì vượt qua thêm cho mỗi ánh sáng, bạn tạo ánh sáng cho dữ liệu theo từng trường hợp và bạn vẽ nó ngay lập tức.

Dựa trên kịch bản đầu tiên, đạo đức của câu chuyện là nếu bất kỳ lớp đối tượng nào cũng có thể sử dụng inst instaging, thì sẽ luôn có ý nghĩa khi luôn sử dụng inst instance cho tất cả các đối tượng của lớp đó.

Dựa trên kịch bản thứ hai, đạo đức của câu chuyện là việc xúi giục có thể có những cách sử dụng không rõ ràng vượt xa chỉ nói "Tôi cần vẽ 20 cây".


Những lý do bạn đưa ra là những lý do tương tự khiến tôi đặt câu hỏi này ngay từ đầu. Cảm ơn bạn.
NPS

12

(Trên hệ thống của tôi, đã không kiểm tra nó ở bất kỳ nơi nào khác) Trong GL, tạo ra một lưới duy nhất (vẽ với số đếm = 1) có một số chi phí khó chịu, nhưng tôi không biết nó đến từ đâu. Tôi đề nghị không làm điều đó.

Tôi đã thử nghiệm điều này trong một ứng dụng thực tế vài tháng trước. Tôi đã mã hóa một số thuật toán chiếu sáng toàn cầu trong cảnh Crytek Sponza, bao gồm khoảng 350 mắt lưới (không nhớ chính xác), trong đó một cặp đôi chia sẻ một số trường hợp. Lúc đầu, tôi đã làm như bạn đề xuất, chỉ cần ví dụ mọi thứ và vẽ phần còn lại với số thể hiện là 1, vì nó đơn giản hóa mã kết xuất một chút.

Sau này khi tối ưu hóa trình kết xuất, chỉ cần chuyển trở lại từ việc kích hoạt số lượng = 1 đối tượng để gửi chúng theo cách thông thường đã tiết kiệm cho tôi khoảng 3,5 mili giây trên mỗi khung hình trên i7 3770k (và GTX 770). Chuyển đổi các mắt lưới với nhiều trường hợp để thực hiện chúng theo cách truyền thống giúp tôi tiết kiệm thêm 0,5ms. Nhìn chung, ứng dụng đã tăng từ ~ 120 FPS lên khoảng ~ 230 FPS.

Tất nhiên, những số liệu này luôn phụ thuộc vào vị trí tắc nghẽn trong ứng dụng của bạn và 0,5ms sau có thể thực sự trở thành chậm trong một ứng dụng mà bạn rất bị ràng buộc trong cuộc gọi. Nhưng nếu không, theo kinh nghiệm của tôi, việc khởi động có một số chi phí khó chịu nếu bạn không vẽ nhiều thứ cùng một lúc.


Thật thú vị, nhưng thật tuyệt khi thấy dữ liệu cho trình điều khiển AMD và Intel, nếu không, bạn thực sự nên nói "Trên hệ thống của tôi" thay vì "Trong GL". Mặt khác, ngay cả khi nó không phải là vấn đề với các triển khai khác, thì thực tế là nó có thể là một lý do đủ để tránh gây ra nếu bạn không sử dụng nó.
bcrist

2

Bạn có thể chắc chắn rằng việc vẽ một đối tượng đơn lẻ có giá trị cao hơn so với vẽ một đối tượng bình thường. Để kích hoạt GPU đang chuẩn bị cho một lượng lớn đối tượng và sự chuẩn bị này sẽ khác với một đối tượng. Tuy nhiên, khoảng cách hiệu suất này lớn đến mức nào chỉ có thể được tìm thấy bằng cách thử nghiệm và rất nhiều tùy thuộc vào thiết lập kết xuất thực tế của bạn. Cách duy nhất để biết chắc chắn là bằng cách tự kiểm tra nó. Điểm chuẩn một lệnh gọi vẽ duy nhất là khó khăn ở đây là một vài ý tưởng về cách bạn có thể tiến hành.


2

Đã 4 năm rồi ... và tôi nghĩ thật an toàn khi nói rằng hoàn toàn ổn khi gửi các cuộc gọi rút thăm "có bản năng" với 1. Như bạn có thể nhận thấy, các API mới DX12Vk đều có số lượng cá thể có thể từ 0 đến SỐ MỘT SỐ . Cũng lưu ý rằng không có Draw Indexed (...) .

BIÊN TẬP

Lưu ý, những điều trên có lẽ là ổn với các API hiện đại này, có thể sử dụng một cái gì đó cũ như Gl <3.3 hoặc có lẽ DX11 sẽ yêu cầu một số hồ sơ như được đề cập bởi những người dùng khác.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.