Cách tiếp cận tốt để xử lý đồng phục trong OpenGL hiện đại là gì?


8

Tôi đang tạo một trình kết xuất bằng OpenGL hiện đại (3.1 trở lên) và bây giờ tôi đang cố gắng tạo ra một cách xử lý đồng phục hiệu quả nhưng linh hoạt. Tôi đã đọc về các đối tượng bộ đệm thống nhất và cách tiếp cận 'phổ biến' là sử dụng chúng (điều không may sau này không mang lại cho tôi nhiều kết quả như tôi mong đợi).

Để giảm các cuộc gọi API OpenGL và lưu trữ dữ liệu trong bộ nhớ liền kề, tôi đang xem xét việc tạo nhiều bộ đệm lớn cho mỗi cấu trúc dữ liệu sẽ được tải lên GPU. Mỗi bộ đệm có kích thước tối đa 16kb (vì theo những gì tôi hiểu thì phần lớn này được đảm bảo có sẵn cho một UBO). Khi một đối tượng muốn có thể tải đồng phục lên GPU, nó sẽ tìm bộ đệm đầu tiên của loại được tải lên chưa đầy đủ và nhận được chỉ mục có sẵn tiếp theo trong bộ đệm đó. Khi đối tượng được vẽ, nó liên kết UBO (nếu chưa bị ràng buộc) và tải lên chỉ mục phần tử của UBO.

Điều này dẫn đến một cái gì đó như thế này:

layout(std140) uniform ModelData { 
    mat4 model_matrix[kNumInstancesPerModelUbo]; 
}
uniform int u_ModelDataIndex;

layout(std140) uniform SkeletonData { 
    mat4 bone_transforms[kNumInstancesPerSkeletonUbo][kMaxBones]; 
}
uniform int u_SkeletonDataIndex;

Tuy nhiên tôi cũng đang xem xét những điều sau:

layout(std140) uniform MeshData {
    mat4 model_matrix[kNumInstancesPerMeshUbo];
    mat4 bone_transforms[kNumInstancesPerMeshUbo][kMaxBones];
}
uniform int u_MeshDataIndex;

Trong một số cách, điều này cảm thấy sạch hơn rất nhiều ở chỗ nó cần một chỉ mục duy nhất để truy cập tất cả dữ liệu liên quan đến lưới sẽ được tải lên. Mặt khác, điều này có thể vượt quá tầm kiểm soát (kích thước bộ đệm lớn hơn 16kb, xử lý các dữ liệu không liên quan (ví dụ: lưới không có khung xương) hoặc thậm chí các vấn đề đồng bộ hóa khi bạn không được phép truy cập để nói các xương trong khi tải lên ma trận mô hình) và tôi cũng không chắc điều này sẽ ảnh hưởng đến bố cục bộ nhớ trên GPU như thế nào.

Thành thật mà nói, tôi cảm thấy như bị mắc kẹt ở đây và tôi không thể tìm thấy một ví dụ cụ thể nào về cách bạn xử lý nhanh và linh hoạt của UBO.

Bạn có lời khuyên hay nguồn lực nào cho tôi có thể giúp tôi ở đây không?

Câu trả lời:


2

Suballocating từ một bộ đệm lớn hơn hoàn toàn là cách để đi, với sự cẩn thận. Tôi đến nhiều hơn từ khía cạnh DirectX / Vulkan, nhưng điều này sẽ áp dụng tương tự cho OpenGL (Tôi sẽ không có các cuộc gọi API trực tiếp ở đây trong câu trả lời này). Những điều cần xem xét là như sau:

  • Bạn có cần lập chỉ mục vào bộ đệm lớn hơn không, hoặc bạn có ổn không khi liên kết tài nguyên với phần bù mỗi lần?
  • Bạn đã quan tâm đến bất kỳ / tất cả các hạn chế căn chỉnh cho đồng phục của bạn được đóng gói cùng nhau (căn chỉnh 256 byte là phổ biến) chưa?

Các API đồ họa mới hơn có "bù động" mà bạn có thể chỉ định bằng lệnh vẽ, đây là một cách khá nhanh để gián tiếp truy cập vào một tiểu vùng của bộ đệm. Tuy nhiên, giả sử bạn là bộ đệm ba dữ liệu có thể thay đổi, sẽ có ít hoặc không có sự tranh chấp trong trình điều khiển để ràng buộc dữ liệu (chỉ một số chi phí cố định).

Tóm lại, có, phân bổ các vùng bộ nhớ / bộ đệm lớn hơn và cho thuê lại các vùng đó được coi là thực tiễn tốt nhất. Điều này áp dụng ngay cả với các đối tượng có các shader khác nhau (nếu bộ cấp phát của bạn có thể xử lý nó).


0

Bao gồm một giai đoạn điểm chuẩn cho cả hai giải pháp trong ứng dụng của bạn và sau đó chọn giải pháp chiến thắng khi chạy. Đây là bằng chứng đơn giản, di động, và tương lai. Ý tôi là, bạn có kiểm tra cho điều này, phải không? ;-)

Tôi biết đây là một câu trả lời khá chung chung cho "thực tiễn tốt nhất" cho hiệu suất cao nhưng nếu bạn nghĩ về nó, có hàng ngàn cấu hình mục tiêu có thể và nhiều nhà cung cấp cần xem xét. Nếu bạn cần thêm chút ít đó, hãy trả cho nhà cung cấp của bạn một trình điều khiển được tối ưu hóa cho ứng dụng của bạn.

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.