Saat menulis shader non-sepele (seperti saat menulis kode non-sepele lainnya), orang membuat kesalahan. [rujukan?] Namun, saya tidak bisa hanya debug itu seperti kode lain - Anda tidak bisa hanya melampirkan gdb atau Visual Studio debugger setelah semua. Anda bahkan tidak dapat melakukan debugging printf, karena tidak ada bentuk output konsol. Apa yang biasanya saya lakukan adalah membuat data yang ingin saya lihat sebagai warna, tetapi itu adalah solusi yang sangat sederhana dan amatir. Saya yakin orang-orang telah menemukan solusi yang lebih baik.
Jadi bagaimana saya bisa benar-benar men-debug shader? Apakah ada cara untuk melangkah melalui shader? Bisakah saya melihat eksekusi shader pada vertex / primitive / fragmen tertentu?
(Pertanyaan ini secara khusus tentang cara men-debug kode shader seperti bagaimana seseorang akan men-debug kode "normal", bukan tentang debugging hal-hal seperti perubahan status.)
Jawaban:
Sejauh yang saya tahu tidak ada alat yang memungkinkan Anda untuk melangkah melalui kode dalam shader (juga, dalam hal ini Anda harus dapat memilih hanya pixel / vertex yang ingin Anda "debug", pelaksanaannya cenderung bervariasi tergantung pada itu).
Apa yang saya pribadi lakukan adalah "debugging warna-warni" yang sangat rumit. Jadi saya menaburkan banyak cabang dinamis dengan
#if DEBUG / #endif
penjaga yang pada dasarnya mengatakanJadi Anda dapat "mengamati" informasi debug dengan cara ini. Saya biasanya melakukan berbagai trik seperti menyortir atau memadukan berbagai "kode warna" untuk menguji berbagai peristiwa yang lebih kompleks atau hal-hal non-biner.
Dalam "kerangka" ini saya juga menemukan berguna untuk memiliki satu set konvensi tetap untuk kasus-kasus umum sehingga jika saya tidak harus terus-menerus kembali dan memeriksa warna apa yang saya kaitkan dengan apa. Yang penting adalah memiliki dukungan yang baik untuk hot-reload kode shader, sehingga Anda hampir dapat secara interaktif mengubah data / acara yang dilacak dan mengaktifkan / menonaktifkan visualisasi debug dengan mudah.
Jika perlu men-debug sesuatu yang tidak dapat Anda tampilkan di layar dengan mudah, Anda selalu dapat melakukan hal yang sama dan menggunakan alat analisis satu bingkai untuk memeriksa hasil Anda. Saya telah mendaftarkan beberapa dari mereka sebagai jawaban dari pertanyaan lain ini.
Obv, tidak perlu dikatakan lagi bahwa jika saya tidak "men-debug" pixel shader atau compute shader, saya meneruskan info "debugColor" ini melalui pipa tanpa menginterpolasinya (dalam GLSL dengan
flat
kata kunci)Sekali lagi, ini sangat macet dan jauh dari debugging yang tepat, tetapi saya terjebak dengan tidak mengetahui alternatif yang tepat.
sumber
Ada juga GLSL-Debugger . Ini adalah debugger yang dulu dikenal sebagai "GLSL Devil".
Debugger sendiri sangat berguna tidak hanya untuk kode GLSL, tetapi juga untuk OpenGL. Anda memiliki kemampuan untuk melompat di antara panggilan draw dan mematahkan sakelar Shader. Ini juga menunjukkan Anda pesan kesalahan yang dikomunikasikan oleh OpenGL kembali ke aplikasi itu sendiri.
sumber
Ada beberapa penawaran oleh vendor GPU seperti AMD CodeXL atau NVIDIA's nSight / Linux GFX Debugger yang memungkinkan melangkah melalui shader tetapi terikat pada perangkat keras masing-masing vendor.
Biarkan saya perhatikan bahwa, meskipun mereka tersedia di Linux, saya selalu memiliki sedikit keberhasilan dengan menggunakannya di sana. Saya tidak dapat mengomentari situasi di bawah Windows.
Opsi yang saya gunakan baru-baru ini, adalah memodulasi kode shader saya melalui
#includes
dan membatasi kode yang disertakan ke subset umum GLSL dan C ++ & glm .Ketika saya menemukan masalah, saya mencoba mereproduksinya di perangkat lain untuk melihat apakah masalahnya sama yang mengisyaratkan kesalahan logika (alih-alih masalah driver / perilaku tidak terdefinisi). Ada juga kesempatan untuk mengirimkan data yang salah ke GPU (misalnya dengan buffer yang tidak benar, dll.) Yang biasanya saya hilangkan dengan output debugging seperti dalam jawaban cifz atau dengan memeriksa data melalui apitrace .
Ketika itu adalah kesalahan logika saya mencoba untuk membangun kembali situasi dari GPU pada CPU dengan memanggil kode yang disertakan pada CPU dengan data yang sama. Lalu saya bisa melangkah melalui CPU.
Membangun berdasarkan modularitas kode Anda juga dapat mencoba untuk menulis unittest untuk itu dan membandingkan hasil antara menjalankan GPU dan menjalankan CPU. Namun, Anda harus menyadari bahwa ada kasus sudut di mana C ++ mungkin berperilaku berbeda dari GLSL, sehingga memberi Anda positif palsu dalam perbandingan ini.
Akhirnya, ketika Anda tidak dapat mereproduksi masalah pada perangkat lain, Anda hanya dapat mulai menggali dari mana perbedaan itu berasal. Unittests mungkin membantu Anda mempersempit di mana hal itu terjadi, tetapi pada akhirnya Anda mungkin perlu menuliskan informasi debug tambahan dari shader seperti dalam jawaban cifz .
Dan untuk memberi Anda gambaran di sini adalah diagram alur proses debug saya:
Untuk mengatasinya di sini adalah daftar pro dan kontra acak:
pro
menipu
sumber
Walaupun sepertinya tidak mungkin untuk benar-benar melangkah melalui shader OpenGL, adalah mungkin untuk mendapatkan hasil kompilasi.
Berikut ini diambil dari Sampel Karton Android .
Jika kode Anda dikompilasi dengan benar, maka Anda tidak punya banyak pilihan selain mencoba cara lain untuk mengomunikasikan status program kepada Anda. Anda bisa memberi isyarat bahwa sebagian kode tercapai, misalnya, mengubah warna titik atau menggunakan tekstur yang berbeda. Yang aneh, tetapi tampaknya menjadi satu-satunya cara untuk saat ini.
EDIT: Untuk WebGL, saya melihat proyek ini , tetapi saya baru saja menemukannya ... tidak dapat menjaminnya.
sumber
Ini adalah copy-paste jawaban saya untuk pertanyaan yang sama di StackOverflow .
Di bagian bawah jawaban ini adalah contoh kode GLSL yang memungkinkan untuk menampilkan nilai penuh
float
sebagai warna, pengkodean IEEE 754binary32
. Saya menggunakannya seperti berikut (cuplikan ini memberikanyy
komponen matriks modelview):Setelah Anda mendapatkan ini di layar, Anda bisa mengambil pemetik warna apa saja, memformat warna sebagai HTML (menambahkan
00
kergb
nilai jika Anda tidak membutuhkan presisi yang lebih tinggi, dan melakukan pass kedua untuk mendapatkan byte yang lebih rendah jika Anda melakukannya), dan Anda mendapatkan representasi heksadesimalfloat
sebagai IEEE 754binary32
.Inilah implementasi aktual dari
toColor()
:sumber
Solusi yang bekerja untuk saya adalah kompilasi kode shader ke C ++ - seperti yang disebutkan oleh Nobody. Itu terbukti sangat efisien ketika bekerja pada kode yang kompleks meskipun memerlukan sedikit pengaturan.
Saya telah bekerja sebagian besar dengan HLSL Compute Shaders yang saya kembangkan perpustakaan proof-of-concept yang tersedia di sini:
https://github.com/cezbloch/shaderator
Ini menunjukkan pada Compute Shader dari DirectX SDK Samples, cara mengaktifkan C ++ seperti debugging HLSL dan cara mengatur Tes Unit.
Kompilasi penghitung komputasi GLSL ke C ++ terlihat lebih mudah daripada HLSL. Terutama karena konstruksi sintaks di HLSL. Saya telah menambahkan contoh sepele dari Uji Unit yang dapat dieksekusi pada pelacak ray GLSL Compute Shader yang juga dapat Anda temukan di sumber proyek Shaderator di bawah tautan di atas.
sumber