文章目录
前言
计算着色器是利用GPU来计算的一种着色器程序。本身不属于渲染管线。但因为是GPU编程中的一部分,所以可以读到显存中的各类数据。又因为GPU并发计算能力很强,所以可以把很多运算放到计算着色器中来做,这样可以显著提高我们程序的运行速度。
添加计算着色器相关的文件
在MiniEngine中,我们有渲染管线的上下文环境CommandContext
其中有两类。
图形上下文:GraphicsContext
计算上下文:ComputeContext
这俩分开,应该是有一定的用意,但由于我学的还不够深入,可能还没理解到。
缺点我倒是发现了。当GraphicsContext的输出要作为ComputeContext的输入时,我只能先让GraphicsContext执行结束后,才会执行ComputeContext。这种操作降低了效率。奇怪的是,我不等待结束,最后效果也是没问题的。我只能初步理解为显卡性能比较强。
这里添加好计算着色器所需要的类、文件。顺便我还把一些辅助类的文件添加了进来
整理之后的代码github:
https://github.com/mversace/DirectX12-MiniEngine-Dragon/tree/c3be3481ccee5ba141ab60a6bbcac1fadb5e7928
利用计算着色器计算输入向量的和
这一部分整体来说还是比较简单的。
直接看下shader的实现
struct Data
{
float3 v1;
float3 v2;
};
StructuredBuffer<Data> gInputA : register(t0);
StructuredBuffer<Data> gInputB : register(t1);
RWStructuredBuffer<Data> gOutput : register(u0);
// 总共有32个数据,所以这里每组分32*1个线程
[numthreads(32, 1, 1)]
void main( uint3 DTid : SV_DispatchThreadID )
{
gOutput[DTid.x].v1 = gInputA[DTid.x].v1 + gInputB[DTid.x].v1;
gOutput[DTid.x].v2 = gInputA[DTid.x].v2 + gInputB[DTid.x].v2;
}
numthreads的含义
这代表的是每个线程组内部在xyz方向上的分组。
对于本项目来说,两个输入都是32个数据,采用结构化的缓冲区StructuredBuffer,所以直接在x方向分组就可以了。
你当然也可以在y方向或者z方向分组,那么下边的代码就需要做对应的修改。
例如改成y方向分组也是可以的。
[numthreads(1, 32, 1)]
void main( uint3 DTid : SV_DispatchThreadID )
{
gOutput[DTid.y].v1 = gInputA[DTid.y].v1 + gInputB[DTid.y].v1;
gOutput[DTid.y].v2 = gInputA[DTid.y].v2 + gInputB[DTid.y].v2;
}
对于程序上来说,总体跟渲染差别不大。
- 设置根签名
- 设置计算流水线
- 设置参数
- dispatch分组