UPL9-17-e——参数的系统语义

本章代码关键字

1
2
3
SV_DispatchThreadID        // 调度线程 ID,每个线程的全局索引(系统自动传入)
SV_GroupThreadID // 组内线程 ID,当前线程在组内的局部索引
SV_GroupID // 线程组 ID,当前线程组在整个 Dispatch 中的索引

入口函数参数的系统语义

Compute Shader 的内核入口函数中参数的主要有三个系统语义:

  • SV_GroupID
  • SV_GroupThreadID
  • SV_DispatchThreadID

语义:是 CG / HLSL 中的一种“数据标签”
用来告诉 GPU 某个变量在渲染管线或计算管线中代表什么意义
语义是 Shader 输入、输出变量的角色标签
它告诉 GPU,这个变量从哪里来、要传到哪里去、它在管线中扮演什么角色

具体可见:US2S3L9——语义

例如:新创建出来 Compute Shader 中的默认入口函数的默认参数 id​ 语义就是 SV_DispatchThreadID

1
2
3
4
5
6
7
#pragma kernel CSMain

[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
Result[id.xy] = float4(id.x & id.y, (id.x & 15)/15.0, (id.y & 15)/15.0, 0.0);
}

对于 Compute Shader 内核入口函数中主要使用的这三个语义
他们主要是告诉 GPU,这个变量从哪里来,其中需要存储什么样的数据
GPU 就会通过该变量传入对应的数据

一个入口函数可以拥有多个不同语义的参数:

1
2
3
4
5
6
7
#pragma kernel CSMain

[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID, uint3 gid : SV_GroupID, uint3 gtid : SV_GroupThreadID)
{
Result[id.xy] = float4(id.x & id.y, (id.x & 15)/15.0, (id.y & 15)/15.0, 0.0);
}

三个语义的区别

入口函数传入的数据类型都是 uint3,但是可以有不同的含义

  • SV_GroupID

    线程组 ID,当前线程组在整个 Dispatch​ 中的索引:当前是第几组,假设为 (1,2,0)

    可以理解为:假设处理的是一个贴图,其中包含若干块方块区域(线程组),方块区域内包含若干个格子(线程),
    SV_GroupID​ 语义参数可以知道:当前线程位于第几个方块区域,(1,2,0) 就是方块区域在所有线程组内的坐标

  • SV_GroupThreadID

    组内线程 ID,当前线程在组内的局部索引:当前线程是组内第几个,假设 (4,6,0)

    可以理解为:假设处理的是一个贴图,其中包含若干块方块区域(线程组),方块区域内包含若干个格子(线程),
    SV_GroupThreadID​ 语义参数可以知道:当前线程是当前所在方块区域里的第几个格子,(4,6,0) 就是格子在当前所在方块区域内的坐标

  • SV_DispatchThreadID

    调度线程 ID,每个线程的全局索引(系统自动传入),比如第 N 个像素、第 N 个粒子
    假设一个线程组包含 (8,8,1)​ 个线程,此线程的所在的线程组坐标是 (1,2,0)​,在所在线程组内的相对坐标为 (4,6,0)
    则该线程在所有线程的位置是:(1 * 8 + 4, 2 * 8 + 6, 0 * 1 + 0) = (12, 22, 0)
    可以理解为:唯一线程编号

三个语义对我们的意义

  • 最常用

    SV_DispatchThreadID

    它可以帮助我们直接映射到图像像素(2D 数据)或数组元素(1D 数据)的下标,可以让我们直接处理目标数据

  • 常用

    SV_GroupID​ 和 SV_GroupThreadID

    我们可以利用他们来共享一些内存,或者分块处理大数据