Chapter12 The Compute Shader (Introduction to 3D Game Programming with DirectX 11)笔记

相比于CPU 被设计为 Random Memory Access,GPU 针对single location 以及 sequential location做了很多优化(streaming operation 流操作)。另外 vertex 和pixel由于是互相独立的,因此GPU可以对他们进行并行操作,比如 [NVIDIA09] NVIDIA “Fermi” architecture 可以支持 最多并行16个 流处理器,每个处理器 32 核,共512核。

GPU 的并行在图形渲染方面带来很大优势,而 非图形应用也可以利用GPU的并行优势,这种应用叫做 general purpose GPU (GPGPU) programming。并不是所有的程序都适合用GPU来计算,需要这些应用本身之间执行相同操作,互相独立,可以并行起来才可以。

如图中所示,CS并不属于pipeline的 一部分,而是 在一边作为独立的一部分,可以随时 读写 GPU Resources。它允许我们访问GPU实现数据并行的算法,但不绘制任何物件。

12.1 THREADS AND THREAD GROUPS

在GPU编程中,将许多thread 分成 thread groups里,一个group在一个处理器上运行。一般来说,如果是16核处理器,那最少需要分成 16个 thread group,但实际上,会至少一个处理器上两个thread group,这是因为单个的 group也有可能在等待,此时可以切换执行第二个group,因此可以分成32个froup。

每个thread group里的thread 共享一块内存,不同group内的thread不能访问对方的内存,同步操作也是在一个group发生,不同group内的不会同步。

一个thread group包含 n个thread。实际在硬件中,会把这些thread 分成 warps(Nvidia 一般的warp size是 32 threads,ATI 的“wavefont” 是 64 threads),然后一个warp 会被一个处理器同时处理SIMD32,即 Single Input Multi Data,一个Cuda processor 有32个 core,每个core处理一个 thread,所以是一个warp里有32个thread。在Dx里,也可以指定 thread group的size不是32的倍数,但从性能的方面考虑,最好还是32的倍数。

在Dx中,使用下面方法调用 thread group,生成 3D thread group grid,但书中之后只关心2D 的thread group。

void ID3D11DeviceContext::Dispatch(
        UINT ThreadGroupCountX,
        UINT ThreadGroupCountY,
        UINT ThreadGroupCountZ);

12.2 A SIMPLE COMPUTE SHADER

cbuffer cbSettings
{
    // Compute shader can access values in constant buffers.
};
// Data sources and outputs.
Texture2D gInputA;
Texture2D gInputB;
RWTexture2D<float4> gOutput;
// The number of threads in the thread group. The threads in a group can
// be arranged in a 1D, 2D, or 3D grid layout.
[numthreads(16, 16, 1)]
void CS(int3 dispatchThreadID : SV_DispatchThreadID) // Thread ID
{
    // Sum the xyth texels and store the result in the xyth texel of
    // gOutput.
    gOutput[dispatchThreadID.xy] =
    gInputA[dispatchThreadID.xy] +
    gInputB[dispatchThreadID.xy];
}
technique11 AddTextures
{
    pass P0
    {
        SetVertexShader(NULL);
        SetPixelShader(NULL);
        SetComputeShader(CompileShader(cs_5_0, CS()));
    }
}

1. Global variable access via constant buffers. 通过constant buffer访问全局变量。
2. Input and output resources, which are discussed in the next section. 输入输出资源下节12.3讨论。
3. The [numthreads(X, Y, Z)] attribute, which specifies the number of threads in the thread group as a 3D grid of threads.
4. The shader body that has the instructions to execute for each thread. CS的shader函数体会被每个thread执行。
5. Thread identification system value parameters (discussed in §12.4). 12.4节讨论thread identification。

注意 [numthreads(X, Y, 1)] 的 X 和 Y 可以变化,但正如之前提到的,thread group的数量需要是 32(Nvidia) / 64 (ATI)的倍数,因此最好是64的倍数,这样两种卡都支持。

12.3 DATA INPUT AND OUTPUT RESOURCES

两种资源可以被关联到 compute shader :buffers and textures。

12.3.1 Texture Inputs 输入

Texture2D gInputA;

通过 ID3D11ShaderResourceViews 创建 SRV 关联到shader,然后使用 ID3DX11EffectShaderResourceVariable 在compute shader中设置,和之前用的方法一样。注意这里 SRV 是只读的。

12.3.2 Texture Outputs and Unordered Access Views (UAVs) 输出

RWTexture2D<float4> gOutput;

CS的输出需要带 RW 前缀,表示 读写都可以,前面input是只读的。注意这里用了 <float4>,这跟输出的纹理格式有关,如果输

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值