Tại sao shader hình học này làm chậm chương trình của tôi rất nhiều?


27

Tôi có một chương trình OpenGL và tôi đang hiển thị lưới địa hình. Tôi thay thế các đỉnh trong bộ đệm đỉnh và chưa thực sự tô màu chúng trong shader mảnh. Tôi đang thêm một shader hình học một phần tại một thời điểm.

Trước khi tôi thêm trình đổ bóng hình học, khi tôi chỉ lập trình các bước tạo bóng mảnh và đỉnh của đường ống, tôi đã nhận được khoảng 30+ khung hình. Đủ để tôi không nhận thấy bất kỳ sự sứt mẻ nào. Sau khi thêm shader hình học, tôi nhận được khoảng 5 khung hình mỗi giây. Tại sao? Đây là toàn bộ của shader hình học:

#version 420

layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;

void main()
{
    for (int i = 0; i < gl_in.length(); i++)
    {
        gl_Position = gl_in[i].gl_Position;
        EmitVertex();
    }
    EndPrimitive();
}

Đây có phải chính xác là những gì OpenGL đã làm mà không có trình đổ bóng hình học không?

Câu trả lời:


40

Đây có phải chính xác là những gì OpenGL đã làm mà không có trình đổ bóng hình học không?

Không, không phải vậy. GS là một bước tùy chọn , không phải là bước có mặc định.

Để OpenGL thực thi trình đổ bóng hình học , nó phải thực hiện cái được gọi là " lắp ráp nguyên thủy ". Khi bạn kết xuất một loạt các hình tam giác thông qua GL_TRIANGLE_STRIP, OpenGL sẽ thực hiện các công cụ bên trong để chuyển đổi mỗi 3 đỉnh liền kề thành một tam giác riêng lẻ, sửa đổi thứ tự cuộn dây một cách thích hợp.

Thông thường, khi không sử dụng GS, quy trình này được thực hiện một lần. Tuy nhiên, khi bạn sử dụng GS, nó phải được thực hiện trước khi GS thực thi. Nhưng nó cũng phải được thực hiện sau GS, bởi vì một GS có thể tạo ra một kiểu nguyên thủy hoàn toàn khác (ví dụ như quads).

Vì vậy, bây giờ bạn đang làm cho hệ thống về cơ bản làm một loạt các công việc bổ sung mà không có gì. Rốt cuộc, OpenGL không thể cho rằng GS của bạn không làm gì cả (đó là vấn đề không thể giải quyết được).

Hơn nữa, một số tối ưu hóa không còn hoạt động với sự có mặt của một GS. Xem xét kết xuất chỉ mục.

Mỗi chỉ mục từ một bộ đệm mảng phần tử sẽ tạo ra các đầu ra giống nhau từ một shader đỉnh. Vì vậy, các GPU thường sẽ bộ nhớ cache các kết quả đầu ra trong một bài đăng-T & L bộ nhớ cache . Nếu nó thấy một chỉ mục đã có trong bộ đệm, thì VS không chạy lại; nó chỉ lấy dữ liệu từ bộ đệm.

Nó là gì"? "Nó" là ... đơn vị lắp ráp nguyên thủy . Vâng, thứ đó được chạy hai lần khi bạn sử dụng GS. Các bộ nhớ đệm chỉ mục? Nó chỉ hoạt động cho các đầu vào của GS.

Vậy điều gì xảy ra với đầu ra của GS? Vâng, đó là phụ thuộc phần cứng. Nhưng nó phải đi vào một số loại bộ nhớ đệm. Và vấn đề nằm ở chỗ: bộ đệm đó hoàn toàn không được lập chỉ mục. Nó giống như một tình huống glDrawArrays.

Vì vậy, nếu bạn gửi một bộ đệm chỉ mục của 0, 1, 2, 0, 2, 3, điều này sẽ dịch thành 4 đỉnh trong bộ đệm sau T & L. Nhưng bộ đệm post-GS của các đỉnh hiện có 6 đỉnh trong đó. Bộ đệm hậu GS sử dụng nhiều không gian hơn. Vì vậy, nếu bạn gặp khó khăn trong việc tạo danh sách hoặc dải tam giác được tối ưu hóa sau T & L đúng cách và bạn lật một GS thông qua như của bạn, về cơ bản bạn đã giết khoảng một nửa số hiệu suất đạt được từ tối ưu hóa đó.

Nó không vô dụng, nhưng nó đau.

Thêm vào đó là thực tế là nhiều GPU lớp GL 3.x (còn gọi là: DX10) có bộ đệm hậu GS khá nhỏ. Bộ đệm càng nhỏ, càng ít lệnh GS bạn có thể kích hoạt đồng thời. Vì vậy, phần cứng của bạn có hiệu quả tắc nghẽn trên GS. Bởi vì tessname là một tính năng lớn của phần cứng lớp 4.x, hầu hết các phần cứng như vậy có bộ đệm đủ để khiến GS nặng hơn sử dụng được.

Vì vậy, việc sử dụng một GS có nhiều khả năng làm cho quá trình xử lý đỉnh mã của bạn bị tắc nghẽn. Tất nhiên, bạn luôn có thể sử dụng điều đó cho lợi thế của mình bằng cách làm cho các đỉnh và mảnh vỡ của bạn trở nên phức tạp hơn, vì đó chỉ là hiệu suất miễn phí tại thời điểm đó.

Để biết thêm thông tin về sự chậm chạp do GS gây ra, hãy đọc bài viết này .

Đây là một quy tắc cơ bản về GS: không bao giờ sử dụng GS vì bạn nghĩ rằng nó sẽ giúp hiển thị nhanh hơn . Bạn nên sử dụng nó khi nó làm cho những gì bạn đang cố gắng thực hiện có thể. Nếu những gì bạn đang cố gắng làm là tối ưu hóa, hãy sử dụng thứ khác.

Các ngoại lệ chung cho điều này là:


Tôi đang cố gắng tính độ dốc của mỗi đa giác bằng cách lấy chiều cao cao nhất của nó và trừ đi chiều cao thấp nhất của nó. Tuy nhiên, nếu một shader hình học nhất thiết sẽ làm tôi chậm lại với số tiền này, tôi nghĩ rằng tôi có thể làm điều đó một cách sáng tạo trong shader đỉnh.
Avi

1
@Avi lưu ý rằng các điểm cao nhất và thấp nhất trong một hình tam giác sẽ không cung cấp cho bạn độ dốc của nó; bạn cần cả ba điểm
sam hocevar

2
Cá nhân tôi luôn thấy việc cung cấp thông tin hữu ích hơn cho các sprite điểm so với GS.
Maximus Minimus

1
Có ngoại lệ cho các sprite điểm khái quát cho shader của layout(points) in;? Hay là kích thước đầu ra cố định? Hay có lẽ cả hai?
Philip
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.