Apa yang menyebabkan percabangan di GLSL tergantung pada model GPU dan versi driver OpenGL.
Sebagian besar GPU tampaknya memiliki bentuk operasi "pilih satu dari dua nilai" yang tidak memiliki biaya percabangan:
n = (a==b) ? x : y;
dan terkadang bahkan hal-hal seperti:
if(a==b) {
n = x;
m = y;
} else {
n = y;
m = x;
}
akan dikurangi menjadi beberapa operasi nilai pilih tanpa penalti cabang.
Beberapa GPU / Driver memiliki (memiliki?) Sedikit penalti pada operator perbandingan antara dua nilai tetapi operasi lebih cepat dibandingkan dengan nol.
Di mana mungkin lebih cepat untuk dilakukan:
gl_FragColor.xyz = ((tmp1 - tmp2) != vec3(0.0)) ? E : tmp1;
daripada membandingkan (tmp1 != tmp2)
secara langsung tetapi ini sangat tergantung GPU dan driver jadi kecuali Anda menargetkan GPU yang sangat spesifik dan tidak ada orang lain saya sarankan menggunakan operasi perbandingan dan meninggalkan pekerjaan yang mengoptimalkan ke driver OpenGL sebagai driver lain mungkin memiliki masalah dengan bentuk yang lebih panjang dan menjadi lebih cepat dengan cara yang lebih sederhana dan lebih mudah dibaca.
"Cabang" juga tidak selalu buruk. Misalnya pada GPU SGX530 yang digunakan dalam OpenPandora, scale2x shader ini (30 ms):
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;
}
Berakhir secara dramatis lebih cepat daripada shader yang setara ini (80 ms):
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;
Anda tidak pernah tahu sebelumnya bagaimana kinerja kompiler GLSL tertentu atau GPU tertentu sampai Anda membuat benchmark.
Untuk menambahkan titik (meskipun saya tidak memiliki angka waktu aktual dan kode shader untuk menyajikan Anda untuk bagian ini) Saat ini saya menggunakan sebagai perangkat keras pengujian biasa:
- Intel HD Graphics 3000
- Intel HD 405 Graphics
- nVidia GTX 560M
- nVidia GTX 960
- AMD Radeon R7 260X
- nVidia GTX 1050
Sebagai beragam model GPU yang berbeda dan umum untuk diuji.
Menguji masing-masing dengan driver OpenGL & OpenCL Linux, proprietary, dan Linux open source.
Dan setiap kali saya mencoba mengoptimalkan mikro shader GLSL (seperti pada contoh SGX530 di atas) atau operasi OpenCL untuk satu kombo GPU / Driver tertentu, saya pada akhirnya sama-sama melukai kinerja pada lebih dari satu GPU / Driver lain.
Jadi, selain dengan jelas mengurangi kompleksitas matematika tingkat tinggi (misalnya: mengonversi 5 divisi identik menjadi satu timbal balik dan 5 perkalian sebagai gantinya) dan mengurangi pencarian tekstur / bandwidth, kemungkinan besar akan membuang-buang waktu Anda.
Setiap GPU terlalu berbeda dari yang lain.
Jika Anda akan bekerja secara khusus pada (a) konsol game dengan GPU tertentu, ini akan menjadi cerita yang berbeda.
Aspek lain (kurang signifikan untuk pengembang game kecil tetapi masih terkenal) dari ini adalah bahwa driver GPU komputer suatu hari nanti diam-diam mengganti shader Anda ( jika game Anda menjadi cukup populer ) dengan yang ditulis ulang kustom dioptimalkan untuk GPU tertentu. Melakukan itu semua bekerja untuk Anda.
Mereka akan melakukan ini untuk game populer yang sering digunakan sebagai tolok ukur.
Atau jika Anda memberi pemain Anda akses ke shader sehingga mereka dapat dengan mudah mengeditnya sendiri, beberapa dari mereka mungkin memeras beberapa FPS tambahan untuk keuntungan mereka sendiri.
Misalnya ada paket shader & tekstur buatan fan untuk Oblivion untuk secara dramatis meningkatkan frame rate pada perangkat keras yang nyaris tidak bisa dimainkan.
Dan terakhir, setelah shader Anda menjadi cukup kompleks, game Anda hampir selesai, dan Anda mulai menguji pada perangkat keras yang berbeda, Anda akan cukup sibuk hanya memperbaiki shader Anda untuk bekerja sama sekali pada berbagai GPU karena itu disebabkan oleh berbagai bug yang Anda tidak inginkan. punya waktu untuk mengoptimalkan mereka ke tingkat itu.