ComputeSharp,在GPU上运行C#

2021-02-24 21:36:43

ComputeSharp是一个.NET Standard 2.1库,可通过DX12和动态生成的HLSL计算着色器在GPU上并行运行C#代码。可用的API使您可以分配GPU缓冲区并将计算着色器编写为简单的lambda表达式或本地方法,所有捕获的变量都将自动处理并传递给正在运行的着色器。

ComputeSharp公开了一个Gpu类,该类充当所有公共API的入口点。它公开了Gpu.Default属性,该属性使您可以访问当前计算机上的主GPU设备,该属性可用于分配缓冲区和执行操作。

下面的示例演示如何分配可写缓冲区,使用计算着色器填充该缓冲区以及将其读回。

//定义一个简单的着色器public readonly struct MyShader:IComputeShader {public readonly ReadWriteBuffer<浮动>缓冲; public MyShader(ReadWriteBuffer< float>缓冲区){this。缓冲=缓冲; } public void Execute(ThreadIds ids){buffer [ids。 X] = ID。 X; }} //在GPU上分配可写缓冲区,并使用ReadWriteBuffer<浮动>缓冲区= Gpu。默认。 AllocateReadWriteBuffer<浮动>(1000); //运行着色器Gpu。默认。 For(1000,新的MyShader(缓冲区)); //将数据取回float [] array = buffer。 GetData();

如果C#中的着色器正在捕获某些局部变量,则这些局部变量将被自动复制到GPU,这样HLSL着色器将能够像您期望的那样访问它们。此外,ComputeSharp还可以解析着色器中使用的静态字段。捕获的变量需要转换为有效的HLSL类型:标量类型(int,uint,float等)或已知的HLSL结构(例如Vector3)。这是库当前支持的变量类型的列表:

✅HLSL类型:Bool,Bool2,Bool3,Bool4,Float2,Float3,Float4,Int2,Int3,Int4,UInt2,Uint3等

带有有效HLSL签名的Func&T或委托,目标方法为静态

有许多用于GraphicsDevice类的扩展API,可用于分配三种类型的GPU缓冲区:ConstantBuffer< T> ReadOnlyBuffer< T>。和ReadWriteBuffer< T>。前者压缩为16个字节,并提供对缓冲区元素的尽可能最快的访问,但是它的最大大小有限(约64KB),并且如果每个元素的大小都不是其倍数,则在往返之间复制数据时需要额外的开销。 16.其他缓冲区类型紧密包装,适用于所有类型的操作,可以认为C#中T []数组的HLSL等效项。如果您不确定要使用哪种缓冲区类型,请使用ReadOnlyBuffer< T>。或ReadWriteBuffer< T&gt ;,这取决于您是否还需要对GPU端的该缓冲区进行写访问。

注意:尽管分配缓冲区的API只是带有T:非托管约束的通用方法,但它们仅应与完全映射到HLSL类型的C#类型一起使用。这意味着int,uint,float,double,.NET矢量类型或HLSL类型。由于C#/ HLSL的差异,不应在缓冲区中使用bool类型:请改用Bool类型。

ComputeSharp使您可以在1到3维的线程组上分派计算着色器,包括对常量和只读缓冲区的支持等等。此外,大多数HLSL内在函数可通过Hlsl类获得。这是展示所有这些功能的更高级的示例。

//使用一些实用程序静态函数定义一个类public static class Activations {public static float Sigmoid(float x)=> 1 /(1 + Hlsl。Exp(-x));} //定义着色器公共只读结构ActivationShader:IComputeShader {private readonly int width;公共只读ReadOnlyBuffer<浮动> X;公共只读ReadWriteBuffer<浮动> y; public ActivationShader(int width,ReadOnlyBuffer< float> x,ReadWriteBuffer< float> y){this。宽度=宽度;这。 x = x;这。 y = y; } public void Execute(ThreadIds ids){int offset = ids。 X + ID。 Y *宽度;浮标= Hlsl。 Pow(x [offset],2); y [offset] =激活。乙状结肠(战俘); }} int height = 10,width = 10; float [] x =新的float [高*宽]; //求和为y的数组float [] y = new float [height * width]; //使用ReadOnlyBuffer<的结果数组(假设两者都有一些值);浮动> xBuffer = Gpu。默认。 AllocateReadOnlyBuffer(x);使用ReadWriteBuffer<浮动> yBuffer = Gpu。默认。 AllocateReadWriteBuffer(y); //运行着色器Gpu。默认。 For(width,height,new ActivationShader(width,xBuffer,yBuffer)); //取回数据并将其写入y数组yBuffer。 GetData(y);

ComputeSharp库需要.NET Standard 2.1支持,并且可用于面向以下应用程序:

此外,您需要具有.NET Core 3.1和C#8.0支持的IDE才能在PC上编译库和示例。

ComputeSharp库基于Amin Delavar的DX12GameEngine存储库中的某些代码。此外,ComputeSharp使用以下存储库中的NuGet软件包(不包括来自Microsoft的软件包):