Apakah itu membantu untuk mendeklarasikan variabel di luar lingkup fungsi utama Anda di GLSL? Apakah variabel-variabel ini benar-benar digunakan kembali dan lebih efisien?
Berikut ini kode yang dimaksud:
varying vec2 vposition;
uniform float seed;
uniform float top;
uniform float bottom;
uniform float phi;
uniform float theta;
uniform float scaledPI;
uniform float yn;
uniform float ym;
uniform float rx;
uniform float ry;
uniform float radius;
const float PI = 3.141592653589793238462643383;
float left;
float right;
float mscaled;
float xn;
float xm;
void main() {
float t = vposition.y * yn + ym;
if(t <= 0.0 || t >= PI){
left = phi - PI;
right = phi + PI;
}else{
mscaled = scaledPI / (1 - abs(Math.cos(theta)));
mscaled = mscaled < PI ? mscaled : PI;
left = phi - mscaled;
right = phi + mscaled;
}
xn = (left - right) / ((-rx / 2.0) - (rx / 2.0));
xm = left - ((-rx/2.0) * xn);
float p = vposition.x * xn + xm;
vec3 coords = vec3( sin(p) * sin(t), cos(t), cos(p) * sin(t) );
float nv = surface( vec4( coords, seed ) );
gl_FragColor = vec4( vec3( nv, nv, nv ), 1.0 );
}
main()
fungsinya? Apakah nilai Anda sebenarnya variabel global (seragam atau atribut dalam bahasa GLSL) atau nilai konstan?Jawaban:
Saya pikir saya mendapatkan apa yang Anda coba tanyakan. Saya menganggap perhatian utama Anda adalah variabel tidak seragam yang didefinisikan di luar
main()
:Mari kita lihat bagaimana GPU dan GLSL bekerja. GPU tidak memiliki tumpukan atau catatan aktivasi panggilan. Tidak ada cara untuk mensimulasikan lingkup atau variabel lokal dalam GLSL seperti yang dapat dilakukan oleh kompiler C pada kebanyakan CPU. Semua yang ada adalah register, yang merupakan register seragam, input stage shader, output, dan file register lokal yang unik untuk permintaan shader itu.
Dengan kata lain, karena tidak ada yang namanya fungsi atau stack atau heap, semua variabel yang dideklarasikan di mana saja tinggal dalam register. Apakah mereka lokal ke beberapa ruang lingkup di GLSL atau global ke seluruh file tidak ada bedanya. Mereka hanya mendaftar.
Namun, pengalokasi register bukan bagian dari standar GLSL. Implementasi OpenGL yang berbeda dapat memiliki tingkat kualitas yang berbeda ketika datang untuk mengubah kode GLSL tingkat tinggi menjadi kode mesin tingkat rendah yang dipahami oleh GPU. Salah satu bagian yang lebih rumit dari kompiler (GLSL atau lainnya) adalah alokasi register . Ini adalah bagian dari kompiler yang menentukan register mana yang ditempati variabel tertentu. C memiliki sedikit lebih sulit karena biasanya harus berurusan dengan file register yang sangat kecil (terutama pada x86) dan harus berurusan dengan mendaftar tumpah (memindahkan variabel ke stack) dan aliasing (menyimpan variabel kembali ke RAM sebelum memanggil fungsi) dan instruksi aneh yang menuntut output berada dalam register tertentu (x86's
idiv
contohnya). GPU memiliki file register berukuran besar karena tidak memiliki tumpukan atau tumpukan, sehingga pengalokasi dapat lebih sederhana.Namun, file register tidak terbatas. Jika Anda memiliki lebih banyak variabel daripada register yang didukung oleh perangkat keras Anda, kompiler harus mencoba menyesuaikan semua variabel Anda dalam register. Ini biasanya memerlukan beberapa bentuk pengecekan kisaran lives . Artinya, jika Anda menggunakan variabel
xn
untuk satu perhitungan lalu tidak pernah menggunakannya lagi, kompiler dapat menentukan ini dan kemudian tahu bahwa register yang ditempatixn
dapat digunakan oleh variabel lain di kemudian hari, sehingga memungkinkan lebih banyak variabel daripada register yang ada (begitu lama karena tidak ada terlalu banyak variabel langsung sekaligus).Kompiler mungkin tidak melakukan ini. Tidak punya. Atau mungkin melakukannya hanya dalam beberapa kasus. Lingkup yang diberikan penyusun yang lebih sederhana masalah yang jauh lebih mudah untuk dipecahkan. Semua register yang dialokasikan untuk variabel fungsi lokal dapat digunakan kembali setelah fungsi itu keluar karena ia tahu variabelnya sudah mati. Variabel global tidak memiliki jaminan semudah itu. Oleh karena itu, beberapa kompiler yang kurang mampu mungkin tidak mengoptimalkan masa pakainya juga, dan variabel global akan selalu memakan register. Ini tidak akan membuat apa pun lebih lambat tetapi mungkin pada beberapa driver membatasi ukuran shader yang dapat Anda tulis.
Secara umum, saya akan sangat menyarankan agar semua variabel terlokalisasi. Pertahankan definisi sedekat mungkin dengan penggunaan variabel. Ini berlaku untuk semua bahasa pemrograman, bukan hanya GLSL. Saya juga merekomendasikan membuat setiap "variabel" const dalam setiap kasus yang Anda bisa. Ini sekali lagi dapat menjadi petunjuk bagi kompiler yang kurang mampu tertentu bahwa optimasi tertentu dimungkinkan, dan yang lebih penting, itu membuat kode Anda lebih banyak mendokumentasikan diri dan mudah untuk dipelihara.
Dan tentu saja, inilah saran Anda "hanya profil untuk menguji dan mencari tahu pasti" saran. Tulis shader Anda dengan dan tanpa global Anda dan profil itu. Setiap dan semua saran kinerja daring harus tidak dipercaya dan diasumsikan dicurigai atau kedaluwarsa.
sumber