Mengapa pixel shaders tidak membiarkan kami membaca langsung dari framebuffer atau buffer kedalaman?

18

Membiarkan saya mencicipi framebuffer atau depthbuffer dalam pixel shader akan menjadi fitur yang sangat berguna. Bahkan hanya dengan mengetahui kedalaman atau warna apa pun yang ada di belakang piksel saat ini akan bermanfaat.

Mengapa OpenGL dan DirectX tidak membiarkan saya melakukan ini? Saya mengharapkan ada semacam batasan perangkat keras, tetapi alpha blending menggunakan warna dalam framebuffer untuk perhitungan blending, dan uji-Z sampel buffer kedalaman di lokasi saat ini. Mengapa tidak membuka nilai-nilai ini secara langsung? Bisakah saya berharap melihat ini di masa depan?

Hannesh
sumber

Jawaban:

20

Ini adalah batasan perangkat keras. Shader fragmen adalah bagian dari jalur pipa yang dapat diprogram, tetapi perpaduan warna akhir dengan buffer target tidak dapat diprogram dalam perangkat keras / komoditas yang tersedia secara luas pada titik ini (ini dapat dikonfigurasi melalui negara campuran, tetapi Anda tidak dapat menulis secara sewenang-wenang. kode yang menggantikan operasi campuran built-in GPU).

Alasan mengapa perangkat keras tidak dibuat untuk ini mungkin ada hubungannya dengan fakta bahwa GPU paralel secara masif; mereka memproses banyak fragmen sekaligus. Beberapa fragmen tersebut pada akhirnya dapat berinteraksi satu sama lain dalam buffer tujuan, tetapi karena sifat proses sinkronisasi fragmen yang tidak sinkron, tidak mungkin untuk mengetahui bagaimana sampai setelah fragmen diproses dan warna akhir telah dipancarkan ... yang menang selalu terjadi secara deterministik.

Hanya karena piksel A akan berada di belakang piksel B dalam bingkai terakhir tidak berarti bahwa piksel A akan selalu menyelesaikan pemrosesan fragmen dan ditulis ke tujuan sebelum B, terutama di beberapa frame rendering. Jadi nilai yang dibaca dari buffer tujuan selama pemrosesan piksel B tidak akan selalu menjadi piksel A - terkadang itu adalah nilai yang jelas.

Jadi saya menduga bahwa melarang buffer tujuan langsung membaca selama tahap fragmen jauh lebih berkaitan dengan menghentikan programmer shader dari menembak dirinya sendiri di kaki dengan mendapatkan hasil berpotensi nondeterministik dari pembacaan itu daripada dari keterbatasan teknis aktual dalam membuat tahap campuran sepenuhnya- dapat diprogram. Dengan menjaga agar operasi baca tetap terkontrol (uji kedalaman, misalnya), GPU memastikan bahwa operasi yang dilakukan dengan nilai baca masuk akal.

Yang mengatakan, mungkin ada hal biaya / manfaat yang terjadi. Membuat aspek pipeline GPU yang dapat diprogram akan menyulitkan desain chip, dan kebutuhan / permintaan untuk buffer tujuan dibaca relatif rendah dibandingkan dengan fitur lainnya.


sumber
Hanya untuk memperluas ini, alasan historis mengapa akses framebuffer lambat adalah karena instruksi sangat banyak pipelined. Mendapatkan akses ke pixel framebuffer yang diberikan akan melibatkan penghentian pipa saat ini sampai semua pipa lain dibilas untuk menyelesaikan render apa pun yang relevan dengan piksel yang diminta. Bahkan dalam kasus aneh dari GPU yang sepenuhnya tidak paralel, Anda masih akan menyiram seluruh pipa untuk setiap permintaan, yang hanya merupakan ide yang buruk. Tidak diragukan lagi hal-hal sedikit berbeda dalam dunia perangkat keras yang dapat diprogram sekarang tetapi saya berharap prinsip yang sama berlaku.
Kylotan
4

Meskipun menjengkelkan, ini memungkinkan produsen perangkat keras fleksibilitas untuk mengoptimalkan proses rendering dengan berbagai cara yang transparan.

Sebagai contoh, perangkat keras PowerVR (tentu digunakan untuk kembali pada hari itu, tidak digunakan satu untuk waktu yang lama) menunggu sampai seluruh adegan yang akan diberikan diserahkan, kemudian melakukan penyortiran kedalaman otomatis menggunakan algoritma pelukis dan tidak benar-benar perlu untuk menghasilkan buffer kedalaman. Ini akan membagi layar menjadi ubin dan membuat masing-masing pada gilirannya.

Roger Perkins
sumber
4

Pixer shader tidak dapat membaca dari buffer warna dan kedalaman karena:

Piksel A dan B dapat diarsir pada saat yang sama persis di perangkat keras, meskipun B akhirnya merender di atas ("setelah") piksel A.

Jika Anda membuatnya sehingga perangkat keras dijamin untuk menaungi A sebelum B, maka bagian dari perangkat keras akan duduk melakukan apa-apa sementara A berbayang, dan kemudian bagian perangkat keras akan duduk melakukan apa-apa sementara B berbayang.

Dalam kasus terburuk yang bisa dibayangkan, semua piksel yang Anda naungi render di atas satu sama lain, dan ribuan demi ribuan utas GPU - semua kecuali satu - duduk diam. Utas yang satu ini dengan sabar menaungi piksel A, lalu B, lalu ...

bmcnett
sumber