Anunciamos ComputeSharp 2.0: ejecute C# en la GPU con facilidad a través de DirectX 12 y D2D1.

Nov 30 2022
¡Después de más de 2 años de trabajo, me complace anunciar que ComputeSharp 2.0 finalmente está disponible! Esta es una reescritura completa de la biblioteca, con soporte para ambos.

¡Después de más de 2 años de trabajo, me complace anunciar que ComputeSharp 2.0 finalmente está disponible! Esta es una reescritura completa de la biblioteca, con soporte para .NET Standard 2.0 y .NET 6, nuevos generadores de fuentes para reemplazar completamente la generación de código en tiempo de ejecución, muchas API nuevas, soporte completamente nuevo para sombreadores de píxeles D2D1 también, controles XAML para UWP y WinUI 3, ¡y mucho más!

Se ha invertido mucho esfuerzo en este lanzamiento, y el alcance de todo el proyecto ha crecido mucho con el tiempo, mucho más de lo que había anticipado originalmente. En esta publicación de blog, quiero presentar la biblioteca a aquellos que no están familiarizados con ella, resaltar algunas de las nuevas funciones y mostrar algunos ejemplos de lo que se puede hacer con ella.

Para aquellos que prefieren un formato de video, aquí hay un enlace a mi charla sobre ComputeSharp en .NET Conf 2022 , y para aquellos que solo quieren saltar directamente al código, aquí hay un enlace al repositorio de GitHub también. ¡Pasemos a ComputeSharp 2.0!

Comencemos con un discurso de ascensor para la biblioteca: ComputeSharp es una biblioteca .NET para ejecutar código C# en paralelo en la GPU a través de DX12, D2D1 y sombreadores de cómputo HLSL generados dinámicamente, con el objetivo de hacer que la computación GPU sea fácil de usar para todos. ¡desarrolladores NET! Le permite escribir sombreadores (es decir, código que puede ejecutarse en la GPU) usando C#, y luego hace todo el trabajo pesado para transformar ese código y enviarlo a la GPU en uso en su máquina. Esto se puede usar para acelerar el hardware de todo tipo de cargas de trabajo: procesamiento de imágenes, cálculos paralelos, generación de animaciones sofisticadas, ¡lo que sea! Y todo sin necesidad de profundizar en las API específicas de la plataforma necesarias para que todo esto funcione, ni aprender a escribir HLSL, que es el lenguaje de programación que utiliza DirectX para los sombreadores.

Para un ejemplo práctico, aquí está la aplicación de muestra ComputeSharp en acción:

Aquí puede ver uno de los controles XAML que ComputeSharp ofrece para UWP y WinUI 3 que se usa para representar varios sombreadores de cómputo animados, en este caso se ejecuta en una aplicación WinUI 3. El código fuente completo está disponible en GitHub , y todos los sombreadores que ve se han transferido desde sombreadores GLSL de shadertoy a solo C#, y todos funcionan con ComputeSharp y se ejecutan con sombreadores de cómputo DirectX 12.

Y aquí hay otro ejemplo de ComputeSharp en acción:

Paint.NET 5.0 que muestra un efecto de desenfoque bokeh impulsado por ComputeSharp

También pasé los últimos meses agregando compatibilidad con Direct2D a ComputeSharp, que ahora es un componente fundamental de la próxima versión de Paint.NET 5.0 . ComputeSharp.D2D1 (la versión de la biblioteca para sombreadores de píxeles D2D1) se usa para implementar docenas de efectos de imagen en la aplicación, que están completamente escritos en C# y GPU acelerados a través del poder de D2D. Esto permitió a Rick Brewster , el desarrollador de Paint.NET, aumentar considerablemente la cantidad de efectos que podía ejecutar en la GPU, al mismo tiempo que reducía significativamente la complejidad de la aplicación con respecto a los efectos de GPU D2D, ya que ya no había la necesidad de escribir efectos manualmente en HLSL y compilarlos con un paso de compilación personalizado: ComputeSharp está haciendo todo este trabajo detrás de escena.

Dato curioso: el desenfoque de bokeh que se muestra en la captura de pantalla de Paint.NET anterior es el puerto de Rick de mi muestra de desenfoque de bokeh ComputeSharp.D2D1 , que es a su vez un puerto que hice de mi muestra de desenfoque de bokeh ComputeSharp , que es un puerto de la versión de C# que escribí para ImageSharp , que es un puerto de la versión de Python que el profesor Mike Pound escribió para su video Computerphile sobre efectos de desenfoque bokeh . ¡Ve a comprobarlo!

Y esto también está disponible para los autores de complementos, lo que significa que ahora cualquiera puede usar ComputeSharp.D2D1 para escribir efectos totalmente personalizados y acelerados por GPU para integrarlos en Paint.NET. Lo que antes requería conocimiento de las funciones internas de HLSL y D2D ahora es fácilmente accesible para todos los desarrolladores de C#, con solo unas pocas líneas de código y API amigables de alto nivel.

Si tiene curiosidad por ver cómo se ve un sombreador ComputeSharp, aquí hay uno muy simple: el sombreador hola mundo, que solo muestra un degradado de color animado que cambia con el tiempo. Aquí está el código C# para ello:

Un sombreador de cómputo de DirectX 12 escrito en C# con ComputeSharp

Puede ver cómo el sombreador es simplemente un tipo de estructura de C#, que captura algunos valores (en este caso, un flotante para indicar el tiempo transcurrido) y luego realiza algunos cálculos para calcular el color que se mostrará en la salida. Este es el sombreador completo, que ComputeSharp luego se encargará de procesar en el momento de la compilación a través de un generador de código fuente, para convertirlo a HLSL y también generar código adicional para respaldar su ejecución.

Así es como se ve el código HLSL resultante para este sombreador:

El sombreador HLSL transpilado para el tipo C#

Es fácil ver algunas de las transformaciones que ComputeSharp ha realizado detrás de escena: el sombreador ahora tiene un búfer constante, que se usa para ordenar los valores capturados en la GPU, tiene anotaciones de tamaño de hilo para controlar el envío del sombreador, las verificaciones automáticas de límites tienen agregado, y el sombreador también captura implícitamente la textura de salida y le asigna el píxel resultante. Como desarrollador de C# que usa ComputeSharp, nunca tendrá que preocuparse por nada de esto: el generador de código fuente incluido con ComputeSharp se encargará de todo este trabajo pesado mientras puede escribir C# y beneficiarse de IntelliSense y todas las excelentes herramientas que ofrece C#.

También quiero mostrar un par de ejemplos completos de extremo a extremo de cómo se ve el código en ejecución en la GPU usando ComputeSharp. Hemos visto cómo puede escribir un sombreador, pero es posible que se pregunte si enviarlo es realmente difícil o no. ¡No lo es! Y también hay varias formas de hacerlo, por lo que también puede elegir la que mejor se adapte a sus necesidades.

ComputeSharp ofrece un modo de ejecución entusiasta y un modo gráfico computacional. El primero es particularmente útil si recién está comenzando con la biblioteca, quiere probar cosas o simplemente necesita ejecutar un script simple y no quiere tener que preocuparse por configurar una canalización de ejecución más compleja. Así es como puede ejecutar un sombreador de prueba muy simple:

Modo de ejecución entusiasta en ComputeSharp

¡Eso es todo lo que necesita hacer para ejecutar el código C# en la GPU! Puede ver cómo tenemos un sombreador muy simple, que simplemente multiplica todos los valores en una textura por 2, y luego lo enviamos a través de un búfer grabable que asignamos en la GPU con algunos valores aleatorios. Después de enviar el sombreador, también podemos copiar ese búfer de GPU en la CPU para poder leer su contenido. ComputeSharp expone docenas de API muy fáciles de usar para realizar operaciones comunes como estas, que pueden adaptarse a todos los escenarios, desde simples scripts mínimos hasta arquitecturas más complicadas.

Veamos también un ejemplo usando el modo gráfico computacional:

Modo gráfico computacional en ComputeSharp

Este modo es perfecto si desea crear una canalización de ejecución totalmente personalizada que también pueda aprovechar al máximo el rendimiento de la GPU. En este modo, primero creamos un ComputeContext , que es un objeto que nos permite poner en cola las operaciones en la GPU. Luego, creamos nuestra canalización (incluidas operaciones como distribuir sombreadores, controlar transiciones para sincronizar accesos a recursos compartidos y más) y, finalmente, distribuir eso en la GPU cuando sale del ámbito del contexto. También puede ver cómo aquí estamos aprovechando la sintaxis await using para ejecutar todo este trabajo de forma asincrónica en la GPU, por lo que no bloqueamos el subproceso actual hasta que la GPU termine de procesar nuestra solicitud.

¿Qué pasa con la compatibilidad con XAML? ComputeSharp ofrece dos controles ( ComputeShaderPanel y AnimatedComputeShaderPanel ), que hacen que sea muy fácil integrar un efecto impulsado por ComputeSharp en una aplicación UWP o WinUI 3: simplemente coloque el control XAML en su vista, asígnele un objeto de ejecución de sombreado y listo. bueno para ir!

ComputeShaderPanel utilizado en una vista XAML

Así es como se puede declarar fácilmente un ComputeShaderPanel dentro de una vista. Luego, solo necesita una instancia de IShaderRunner para saber cómo representar cada cuadro. Para casos simples, por ejemplo, cuando solo queremos mostrar una animación de sombreado, el tipo incorporado ShaderRunner<T> es más que suficiente:

Corredor de sombras ser asignado a un ComputeShaderPanel

¡Y eso es! El panel usará el shader runner para dibujar cada cuadro y se encargará de toda la configuración necesaria para mostrar realmente cada cuadro generado. Para escenarios más avanzados, también puede implementar el shader runner usted mismo, lo que le brinda un control total sobre la sincronización del cuadro, el gráfico de cálculo utilizado para producir cada imagen para mostrar, ¡y más!

Finalmente, también quiero mostrar un ejemplo de un sombreador de píxeles D2D1. Estos son los sombreadores que usa Paint.NET, y también son parte de la infraestructura en la que estoy trabajando actualmente para permitir su uso en aplicaciones UWP y WinUI 3 a través de la biblioteca Win2D (también puede ver mi propuesta aquí ). ). Son muy diferentes a los sombreadores de cómputo de DirectX 12, pero gracias a la infraestructura de ComputeSharp son igual de fáciles de implementar y también se pueden ejecutar sin demasiado esfuerzo aprovechando el efecto de sombreado de píxeles integrado que incluye ComputeSharp.D2D1.

Aquí hay un ejemplo de un efecto pixelado de Paint.NET:

Un sombreador de píxeles pixelado D2D1, de Paint.NET

Notará que hay algunas diferencias entre este sombreador y el sombreador DX12 que se muestra arriba, pero la experiencia del desarrollador es prácticamente la misma: solo necesita crear un tipo C#, usar las proyecciones HLSL disponibles y las API que incluye ComputeSharp, dejar que IntelliSense lo guíe. usted, y luego deje que ComputeSharp haga todo el resto del trabajo por usted en tiempo de compilación.

Veamos también el código transpilado para este shader:

El efecto pixelado transpilado a HLSL

Una vez más, el tipo C# se ha transformado según sea necesario para seguir las convenciones HLSL necesarias, en este caso específicamente para sombreadores de píxeles D2D1. Hemos declarado campos para asignarlos a los diversos valores capturados en C#, todos los elementos intrínsecos se han reenviado a sus equivalentes HLSL, la sintaxis del sombreador se ha actualizado y mucho más. Y todos estos sombreadores, al igual que los de DX12, también se pueden precompilar en el momento de la compilación, lo que significa que sus aplicaciones pueden tener un rendimiento de inicio increíblemente rápido y no es necesario invocar o agrupar el compilador de sombreadores una vez implementado.

Hay mucho más que está disponible en ComputeSharp, y esta también es solo la primera versión estable después de la reescritura: ¡hay muchas características nuevas y mejoras en las que ya estoy trabajando y que planeo incluir en versiones futuras! Le invitamos a consultar el repositorio en GitHub , probar la biblioteca ( ¡puede encontrarla en NuGet! ) y dejar comentarios e ideas.

Y si lo usa y crea algo, ¡compártalo! ¡Me encanta ver todas las cosas geniales que la gente puede construir usando ComputeSharp!

¡Feliz codificación!