Mengumumkan ComputeSharp 2.0 — jalankan C# pada GPU dengan mudah melalui DirectX 12 dan D2D1!

Nov 30 2022
Setelah lebih dari 2 tahun bekerja, dengan senang hati saya mengumumkan bahwa ComputeSharp 2.0 akhirnya tersedia! Ini adalah penulisan ulang lengkap dari perpustakaan, menampilkan dukungan untuk keduanya.

Setelah lebih dari 2 tahun bekerja, dengan senang hati saya mengumumkan bahwa ComputeSharp 2.0 akhirnya tersedia! Ini adalah penulisan ulang lengkap pustaka, menampilkan dukungan untuk .NET Standard 2.0 dan .NET 6, generator sumber baru untuk sepenuhnya menggantikan pembuatan kode runtime, banyak API baru, dukungan baru untuk shader piksel D2D1 juga, kontrol XAML untuk UWP dan WinUI 3, dan masih banyak lagi!

Banyak upaya telah dilakukan untuk rilis ini, dan cakupan keseluruhan proyek telah berkembang jauh dari waktu ke waktu, jauh lebih banyak daripada yang saya perkirakan sebelumnya. Dalam posting blog ini saya ingin memperkenalkan perpustakaan kepada mereka yang tidak terbiasa dengannya, menyoroti beberapa fitur baru, dan menunjukkan beberapa contoh tentang apa yang dapat dilakukan dengannya.

Bagi mereka yang lebih suka bentuk video, berikut adalah tautan ke pembicaraan saya tentang ComputeSharp di .NET Conf 2022 , dan bagi mereka yang hanya ingin langsung masuk ke kode, berikut adalah tautan ke repo GitHub juga. Mari lompat ke ComputeSharp 2.0!

Mari kita mulai dengan elevator pitch untuk library: ComputeSharp adalah library .NET untuk menjalankan kode C# secara paralel pada GPU melalui DX12, D2D1, dan shader komputasi HLSL yang dihasilkan secara dinamis, dengan tujuan membuat komputasi GPU mudah digunakan untuk semua . pengembang .NET! Ini memungkinkan Anda menulis shader (yaitu kode yang dapat berjalan di GPU) menggunakan C #, dan kemudian melakukan semua pekerjaan berat untuk mengubah kode itu dan benar-benar mengirimkannya ke GPU yang digunakan di mesin Anda. Ini dapat digunakan untuk perangkat keras mempercepat semua jenis beban kerja — pemrosesan gambar, perhitungan paralel, menghasilkan animasi mewah, sebut saja! Dan semua tanpa Anda perlu menyelam jauh ke dalam API khusus platform yang diperlukan untuk membuat semua ini berfungsi, atau untuk mempelajari cara menulis HLSL, yang merupakan bahasa pemrograman yang digunakan DirectX untuk shader.

Sebagai contoh praktis, inilah Contoh Aplikasi ComputeSharp yang sedang beraksi:

Di sini Anda dapat melihat salah satu kontrol XAML yang ditawarkan ComputeSharp untuk UWP dan WinUI 3 digunakan untuk merender beberapa shader komputasi animasi, dalam hal ini menjalankan aplikasi WinUI 3. Seluruh kode sumber tersedia di GitHub , dan semua shader yang Anda lihat telah dipindahkan dari shader GLSL dari shadertoy ke hanya C#, dan semuanya didukung oleh ComputeSharp dan dijalankan menggunakan shader komputasi DirectX 12.

Dan inilah contoh lain dari tindakan ComputeSharp:

Paint.NET 5.0 menampilkan efek blur bokeh bertenaga ComputeSharp

Saya telah menghabiskan beberapa bulan terakhir menambahkan dukungan Direct2D ke ComputeSharp juga, yang sekarang menjadi komponen fundamental dari rilis Paint.NET 5.0 yang akan datang . ComputeSharp.D2D1 (versi perpustakaan untuk shader piksel D2D1) digunakan untuk mengimplementasikan lusinan efek gambar dalam aplikasi, yang seluruhnya ditulis dalam C# dan GPU dipercepat melalui kekuatan D2D. Hal ini memungkinkan Rick Brewster , pengembang Paint.NET, untuk meningkatkan jumlah efek yang dapat dijalankan pada GPU, sementara pada saat yang sama secara signifikan mengurangi kerumitan aplikasi sehubungan dengan efek GPU D2D, karena tidak ada lagi kebutuhan untuk menulis efek secara manual di HLSL dan mengompilasinya dengan langkah pembuatan khusus — ComputeSharp melakukan semua pekerjaan ini di belakang layar!

Fakta menyenangkan — keburaman bokeh yang ditampilkan dalam tangkapan layar Paint.NET di atas adalah port Rick dari sampel blur bokeh ComputeSharp.D2D1 saya , yang juga merupakan port yang saya buat dari sampel blur bokeh ComputeSharp saya , yang merupakan port dari versi C# yang saya tulis untuk ImageSharp , yang merupakan port dari versi Python yang ditulis profesor Mike Pound untuk video Computerphile miliknya tentang efek bokeh blur . Pergi periksa!

Dan ini juga tersedia untuk pembuat plugin, artinya siapa pun sekarang juga dapat menggunakan ComputeSharp.D2D1 untuk menulis efek yang sepenuhnya dapat disesuaikan dan GPU yang dipercepat untuk diintegrasikan ke dalam Paint.NET. Apa yang dulu membutuhkan pengetahuan internal HLSL dan D2D sekarang mudah diakses oleh semua pengembang C#, hanya dengan beberapa baris kode dan API tingkat tinggi yang ramah.

Jika Anda penasaran untuk melihat seperti apa shader ComputeSharp, inilah yang sangat sederhana: shader hello world, yang hanya menampilkan gradien warna animasi yang berubah seiring waktu. Berikut kode C# untuk itu:

Shader komputasi DirectX 12 yang ditulis dalam C# dengan ComputeSharp

Anda dapat melihat bagaimana shader hanyalah tipe C# struct, yang menangkap beberapa nilai (dalam hal ini float untuk menunjukkan waktu yang berlalu), dan kemudian melakukan beberapa perhitungan untuk menghitung warna yang akan ditampilkan dalam output. Ini adalah keseluruhan shader, yang kemudian akan diproses oleh ComputeSharp pada waktu pembuatan melalui generator sumber, untuk mengonversinya menjadi HLSL dan juga menghasilkan kode tambahan untuk mendukung eksekusinya.

Berikut adalah tampilan kode HLSL yang dihasilkan untuk shader ini:

Shader HLSL yang ditranspilasikan untuk tipe C#

Sangat mudah untuk melihat beberapa transformasi yang telah dilakukan ComputeSharp di belakang layar: shader sekarang memiliki buffer konstan, yang digunakan untuk mengumpulkan nilai yang ditangkap ke GPU, memiliki anotasi ukuran thread untuk mengontrol pengiriman shader, pemeriksaan batas otomatis memiliki telah ditambahkan, dan shader juga secara implisit menangkap tekstur output dan menugaskan piksel yang dihasilkan ke dalamnya. Sebagai pengembang C# yang menggunakan ComputeSharp, Anda tidak perlu khawatir tentang semua ini: generator sumber yang dibundel dengan ComputeSharp akan menangani semua pekerjaan berat ini selagi Anda dapat menulis C# dan memanfaatkan IntelliSense dan semua perkakas hebat yang ditawarkan C#.

Saya juga ingin menunjukkan beberapa contoh lengkap dari ujung ke ujung seperti apa kode yang berjalan pada GPU menggunakan ComputeSharp. Kami telah melihat bagaimana Anda dapat menulis shader, tetapi Anda mungkin bertanya-tanya apakah mengirimkannya sebenarnya sulit atau tidak. Bukan! Dan ada juga beberapa cara untuk melakukannya, jadi Anda juga dapat memilih salah satu yang paling sesuai dengan kebutuhan Anda.

ComputeSharp menawarkan mode eksekusi yang bersemangat, dan mode grafik komputasi. Yang pertama sangat berguna jika Anda baru saja memulai dengan perpustakaan, ingin mencoba berbagai hal atau hanya perlu menjalankan beberapa skrip sederhana dan tidak ingin khawatir tentang menyiapkan pipa eksekusi yang lebih kompleks. Inilah cara Anda menjalankan tes shader yang sangat sederhana:

Mode eksekusi bersemangat di ComputeSharp

Itu saja yang perlu Anda lakukan untuk menjalankan kode C# pada GPU! Anda dapat melihat bagaimana kami memiliki shader yang sangat sederhana, yang hanya mengalikan semua nilai dalam tekstur dengan 2, lalu kami mengirimkannya melalui buffer yang dapat ditulisi yang kami alokasikan pada GPU dengan beberapa nilai acak di dalamnya. Setelah mengirimkan shader, kami juga dapat menyalin buffer GPU itu kembali ke CPU sehingga kami dapat membaca isinya. ComputeSharp memperlihatkan lusinan API yang sangat mudah digunakan untuk melakukan operasi umum seperti ini, yang dapat beradaptasi dengan semua skenario mulai dari skrip minimal sederhana hingga arsitektur yang lebih rumit.

Mari kita lihat juga contoh menggunakan mode grafik komputasi:

Mode grafik komputasi di ComputeSharp

Mode ini sangat cocok jika Anda ingin membuat pipa eksekusi yang disesuaikan sepenuhnya yang juga dapat memaksimalkan kinerja GPU. Dalam mode ini, pertama-tama kita membuat ComputeContext , yang merupakan objek yang memungkinkan kita mengantri operasi pada GPU. Kemudian kami membuat jalur pipa kami (termasuk operasi seperti mengirimkan shader, mengontrol transisi untuk menyinkronkan akses ke sumber daya bersama, dan lainnya), dan terakhir kami mengirimkannya pada GPU saat berada di luar cakupan konteks. Anda juga dapat melihat bagaimana di sini kami memanfaatkan penantian menggunakan sintaks untuk menjalankan semua pekerjaan ini secara asinkron pada GPU, jadi kami tidak memblokir utas saat ini hingga GPU selesai memproses permintaan kami.

Bagaimana dengan dukungan XAML? ComputeSharp menawarkan dua kontrol ( ComputeShaderPanel dan AnimatedComputeShaderPanel ), yang membuatnya sangat mudah untuk mengintegrasikan efek yang didukung ComputeSharp ke dalam aplikasi UWP atau WinUI 3: cukup masukkan kontrol XAML ke tampilan Anda, tetapkan objek shader runner untuk itu, dan Anda' kembali baik untuk pergi!

ComputeShaderPanel digunakan dalam tampilan XAML

Inilah cara ComputeShaderPanel dapat dengan mudah dideklarasikan dalam tampilan. Kemudian, hanya perlu instance IShaderRunner untuk mengetahui cara merender setiap frame. Untuk kasus sederhana, misalnya ketika kita hanya ingin menampilkan animasi shader, tipe ShaderRunner<T> bawaan sudah lebih dari cukup:

ShaderRunner ditugaskan ke ComputeShaderPanel

Dan itu saja! Panel akan menggunakan shader runner untuk menggambar setiap bingkai, dan akan menangani seluruh penyiapan yang diperlukan untuk benar-benar menampilkan setiap bingkai yang dibuat. Untuk skenario yang lebih canggih, Anda juga dapat mengimplementasikan shader runner sendiri, yang memberi Anda kendali penuh atas waktu bingkai, grafik perhitungan yang digunakan untuk menghasilkan setiap gambar untuk ditampilkan, dan banyak lagi!

Terakhir, saya juga ingin menunjukkan contoh shader piksel D2D1. Ini adalah shader yang digunakan Paint.NET, dan mereka juga merupakan bagian dari infrastruktur yang sedang saya kerjakan untuk memungkinkan penggunaan ini ke dalam aplikasi UWP dan WinUI 3 melalui pustaka Win2D (Anda juga dapat melihat proposal saya untuk itu di sini ). Mereka sangat berbeda dari shader komputasi DirectX 12, tetapi berkat infrastruktur ComputeSharp, mereka mudah diimplementasikan, dan juga dapat dijalankan tanpa terlalu banyak usaha dengan memanfaatkan efek shader piksel bawaan yang disertakan ComputeSharp.D2D1.

Berikut adalah contoh efek pixelate dari Paint.NET:

Sebuah pixelate D2D1 pixel shader, dari Paint.NET

Anda akan melihat ada beberapa perbedaan antara shader ini dan shader DX12 yang ditunjukkan di atas, tetapi pengalaman pengembang sebagian besar sama: Anda hanya perlu membuat tipe C#, menggunakan proyeksi HLSL dan API yang tersedia yang disertakan ComputeSharp, biarkan IntelliSense memandu Anda, lalu biarkan ComputeSharp melakukan semua pekerjaan lainnya untuk Anda pada waktu kompilasi.

Mari kita lihat juga kode transpilasi untuk shader ini:

Efek pixelate berubah menjadi HLSL

Sekali lagi, tipe C# telah diubah seperlunya untuk mengikuti konvensi HLSL yang diperlukan, dalam hal ini khusus untuk shader piksel D2D1. Kami telah mendeklarasikan bidang untuk dipetakan ke berbagai nilai yang ditangkap di C#, semua intrinsik telah diteruskan ke HLSL yang setara, sintaks shader telah diperbarui, dan banyak lagi. Dan semua shader ini, seperti yang DX12, juga dapat dikompilasi sebelumnya pada waktu pembuatan, yang berarti aplikasi Anda dapat memiliki kinerja startup yang sangat cepat dan tidak perlu memanggil atau membundel kompiler shader sama sekali setelah diterapkan!

Masih banyak lagi yang tersedia di ComputeSharp, dan ini juga merupakan rilis stabil pertama setelah penulisan ulang — ada banyak fitur baru dan peningkatan yang sedang saya kerjakan dan yang saya rencanakan untuk disertakan dalam rilis mendatang! Anda dipersilakan untuk memeriksa repositori di GitHub , mencoba perpustakaan ( Anda dapat menemukannya di NuGet! ), dan tinggalkan umpan balik dan ide!

Dan jika Anda menggunakannya dan membuat sesuatu — tolong bagikan! Saya sangat senang melihat semua hal keren yang dapat dibuat orang menggunakan ComputeSharp!

Selamat membuat kode!