Điều gì gây ra sự phân nhánh trong GLSL phụ thuộc vào kiểu máy GPU và phiên bản trình điều khiển OpenGL.
Hầu hết các GPU dường như có một hình thức hoạt động "chọn một trong hai giá trị" không có chi phí phân nhánh:
n = (a==b) ? x : y;
và đôi khi cả những thứ như:
if(a==b) {
n = x;
m = y;
} else {
n = y;
m = x;
}
sẽ được giảm xuống một vài thao tác chọn giá trị mà không bị phạt phân nhánh.
Một số GPU / Trình điều khiển đã (có?) Một chút hình phạt đối với toán tử so sánh giữa hai giá trị nhưng hoạt động nhanh hơn so với không.
Nơi nào có thể nhanh hơn để làm:
gl_FragColor.xyz = ((tmp1 - tmp2) != vec3(0.0)) ? E : tmp1;
thay vì so sánh (tmp1 != tmp2)
trực tiếp nhưng điều này phụ thuộc rất nhiều vào GPU và trình điều khiển , trừ khi bạn đang nhắm mục tiêu một GPU rất cụ thể và không có ai khác tôi khuyên bạn nên sử dụng thao tác so sánh và để công việc tối ưu hóa đó cho trình điều khiển OpenGL vì trình điều khiển khác có thể có vấn đề với dạng dài hơn và nhanh hơn với cách đơn giản hơn, dễ đọc hơn.
"Chi nhánh" không phải lúc nào cũng là một điều xấu. Ví dụ: trên GPU SGX530 được sử dụng trong OpenPandora, shader scale2x này (30ms):
lowp vec3 E = texture2D(s_texture0, v_texCoord[0]).xyz;
lowp vec3 D = texture2D(s_texture0, v_texCoord[1]).xyz;
lowp vec3 F = texture2D(s_texture0, v_texCoord[2]).xyz;
lowp vec3 H = texture2D(s_texture0, v_texCoord[3]).xyz;
lowp vec3 B = texture2D(s_texture0, v_texCoord[4]).xyz;
if ((D - F) * (H - B) == vec3(0.0)) {
gl_FragColor.xyz = E;
} else {
lowp vec2 p = fract(pos);
lowp vec3 tmp1 = p.x < 0.5 ? D : F;
lowp vec3 tmp2 = p.y < 0.5 ? H : B;
gl_FragColor.xyz = ((tmp1 - tmp2) != vec3(0.0)) ? E : tmp1;
}
Đã kết thúc nhanh hơn đáng kể so với shader tương đương này (80ms):
lowp vec3 E = texture2D(s_texture0, v_texCoord[0]).xyz;
lowp vec3 D = texture2D(s_texture0, v_texCoord[1]).xyz;
lowp vec3 F = texture2D(s_texture0, v_texCoord[2]).xyz;
lowp vec3 H = texture2D(s_texture0, v_texCoord[3]).xyz;
lowp vec3 B = texture2D(s_texture0, v_texCoord[4]).xyz;
lowp vec2 p = fract(pos);
lowp vec3 tmp1 = p.x < 0.5 ? D : F;
lowp vec3 tmp2 = p.y < 0.5 ? H : B;
lowp vec3 tmp3 = D == F || H == B ? E : tmp1;
gl_FragColor.xyz = tmp1 == tmp2 ? tmp3 : E;
Bạn không bao giờ biết trước trình biên dịch GLSL cụ thể hoặc GPU cụ thể sẽ hoạt động như thế nào cho đến khi bạn đánh giá nó.
Để thêm điểm (ngay cả tho tôi không có số thời gian thực và mã shader để trình bày cho bạn về phần này) Tôi hiện đang sử dụng làm phần cứng kiểm tra thông thường của mình:
- Đồ họa HD HD 3000
- Đồ họa Intel HD 405
- nVidia GTX 560M
- nVidia GTX 960
- AMD Radeon R7 260X
- nVidia GTX 1050
Là một loạt các mô hình GPU khác nhau, phổ biến, để thử nghiệm.
Kiểm tra từng trình điều khiển với Windows, Linux độc quyền và trình điều khiển OpenGL & OpenCL nguồn mở của Linux.
Và mỗi khi tôi cố gắng tối ưu hóa micro shader GLSL (như trong ví dụ SGX530 ở trên) hoặc các hoạt động OpenCL cho một kết hợp GPU / Trình điều khiển cụ thể, tôi sẽ làm tổn hại đến hiệu suất của hơn một trong các GPU / Trình điều khiển khác.
Vì vậy, ngoài việc giảm rõ ràng độ phức tạp toán học cấp cao (ví dụ: chuyển đổi 5 phép chia giống nhau thành một phép đối ứng và 5 phép nhân thay thế) và giảm tra cứu / băng thông kết cấu, rất có thể sẽ lãng phí thời gian của bạn.
Mỗi GPU là quá khác nhau từ những người khác.
Nếu bạn đang làm việc cụ thể trên (a) máy chơi trò chơi với GPU cụ thể thì đây sẽ là một câu chuyện khác.
Một khía cạnh khác (ít quan trọng hơn đối với các nhà phát triển trò chơi nhỏ nhưng vẫn đáng chú ý) ở đây là trình điều khiển GPU máy tính có thể một ngày âm thầm thay thế các shader của bạn ( nếu trò chơi của bạn đủ phổ biến ) với các tùy chỉnh được viết lại được tối ưu hóa cho GPU cụ thể đó. Làm điều đó tất cả làm việc cho bạn.
Họ sẽ làm điều này cho các trò chơi phổ biến thường được sử dụng làm điểm chuẩn.
Hoặc nếu bạn cung cấp cho người chơi của mình quyền truy cập vào các shader để họ có thể dễ dàng tự chỉnh sửa chúng, một số trong số họ có thể ép thêm một vài FPS vì lợi ích riêng của họ.
Ví dụ, có các gói đổ bóng và kết cấu do quạt tạo ra cho Oblivion để tăng đáng kể tốc độ khung hình trên phần cứng hầu như không thể phát.
Và cuối cùng, khi trình tạo bóng của bạn đủ phức tạp, trò chơi của bạn gần như đã hoàn thành và bạn bắt đầu thử nghiệm trên các phần cứng khác nhau, bạn sẽ bận rộn đủ để sửa các trình tạo bóng của bạn hoạt động trên nhiều loại GPU khác nhau do các lỗi khác nhau mà bạn không gặp phải. có thời gian để tối ưu hóa chúng đến mức độ đó.