2013-07-25 35 views
5

Apple cho biết trong thực tiễn tốt nhất của họ đối với Shaders là avoid branching nếu có thể và đặc biệt phân nhánh các giá trị được tính trong trình đổ bóng. Vì vậy, tôi đã thay thế một số câu hỏi if bằng chức năng tích hợp sẵn trong clamp(). Câu hỏi của tôi là, là clamp(), min()max() có khả năng hiệu quả hơn hoặc chúng chỉ đơn thuần là các chức năng tiện lợi (tức là vĩ mô) mà chỉ cần mở rộng tới các khối if?Thực hành tốt nhất OpenGL ES cho điều kiện

Tôi nhận ra câu trả lời có thể phụ thuộc vào việc triển khai. Trong mọi trường hợp, các chức năng rõ ràng là sạch hơn và làm cho đồng bằng ý định, mà trình biên dịch có thể làm điều gì đó với.

+2

Tôi nghĩ câu cuối cùng của bạn đã được trả lời khá tốt. Ngoài việc tìm kiếm được sắp xếp hợp lý hơn, chúng ít có khả năng được thực hiện bởi các hướng dẫn phần cứng nhanh hơn một 'if' đơn giản. Và ngoài đề xuất chung này (mà nên là đã đủ, mặc dù), trong thực tế nó thực sự là khá có khả năng rằng họ sử dụng hướng dẫn phần cứng đặc biệt hoặc bài tập có điều kiện và không chỉ là chức năng gói 'if's. –

Trả lời

9

Các GPU đã từng hỗ trợ các hướng dẫn từng đoạn như MINMAX lâu hơn nhiều so với chúng đã hỗ trợ phân nhánh có điều kiện tùy ý. Một ví dụ về điều này trong OpenGL trên máy tính để bàn là phần mở rộng GL_ARB_fragment_program (hiện được thay thế bởi GLSL), tuyên bố rõ ràng rằng nó không hỗ trợ phân nhánh, nhưng nó cung cấp hướng dẫn cho MINMAX cũng như một số hướng dẫn có điều kiện khác.

Tôi rất tự tin rằng tất cả các GPU vẫn sẽ có phần cứng chuyên dụng cho các hoạt động này được cung cấp cách phổ biến min(), max()clamp() nằm trong trình đổ bóng. Điều này không được đảm bảo bởi đặc điểm kỹ thuật bởi vì việc triển khai có thể tối ưu hóa mã tuy nhiên nó thấy phù hợp, nhưng trong thế giới thực, bạn nên sử dụng các hàm dựng sẵn của GLSL thay vì cuộn của riêng bạn.

Ngoại lệ duy nhất sẽ là nếu điều kiện của bạn được sử dụng để tránh một số lượng lớn xử lý phân đoạn bổ sung. Tại một thời điểm nào đó chi phí của chi nhánh sẽ thấp hơn chi phí chạy tất cả mã trong chi nhánh, nhưng số dư ở đây sẽ rất phụ thuộc phần cứng và bạn phải chuẩn bị để xem liệu nó có thực sự giúp ích cho ứng dụng của bạn hay không phần cứng mục tiêu. Dưới đây là các loại điều tôi muốn nói là:

void main() { 
    vec3 N = ...; 
    vec3 L = ...; 
    float NDotL = dot(N, L); 
    if (NDotL > 0.0) 
    { 
     // Lots of very intensive code for an awesome shadowing algorithm that we 
     // want to avoid wasting time on if the fragment is facing away from the light 
    } 
} 

Chỉ cần kẹp NDotL đến 0-1 và sau đó luôn chế biến mã bóng trên mỗi đoạn chỉ để nhân thông qua hạn bóng cuối cùng của bạn bởi NDotL được rất nhiều nỗ lực lãng phí nếu NDotL ban đầu là < = 0 và chúng tôi về mặt lý thuyết có thể tránh được chi phí này bằng chi nhánh. Lý do loại điều này không phải luôn luôn là một chiến thắng hiệu suất là nó rất phụ thuộc vào cách phần cứng thực hiện phân nhánh đổ bóng.

+0

Đánh giá tuyệt vời. Tôi nên nhận ra 'MIN' và' MAX' trước tiên 'if' khối, và tôi chắc chắn bạn đang đúng về hỗ trợ phần cứng cho những. Cảm ơn nhiều! –

+0

Tôi nghĩ rằng một cái gì đó mà nên được đề cập, là một số GPU không tôn trọng các tiêu chuẩn và thậm chí không thực hiện các chi nhánh ở tất cả. Những người duy nhất tôi gặp phải là loạt Galaxy Tab của Samsung. Họ chỉ im lặng sụp đổ mà không có thông điệp hay gì cả. –

Các vấn đề liên quan