UGP1-2 ComputeShader语法
[toc]本篇讨论UnityGraphicsPrograming第一册第二章内容 ComputeShader(CS)语法 参考资料: https://docs.unity3d.com/Manual/class-ComputeShader.html https://docs.unity3d.com/Manual/SL-SamplerStates.html 在Manul左侧的目录中也存在很多值的参考的消息 ▲Thread相关常数 参考资料:微软DX官方文档 Kernel:一个GPU任务,需要在CS代码中声明;computeShader.FindKernel(“KernelName”); Thread Group:Kernel的执行单元;computeShader.Dispatch(kernelID, a, b, c); 同时执行的Thread Group数为a * b * c,左上角为(0,0,0),右为X轴正方形,下为Y轴正方向,Z表示阵列厚度; SV_GroupID:类似的宏表示CS代码中的常数;组坐标;Thread所在的Thread Group的坐标; 根据情况,如果只指定x和y值不为1,有助于提升效率。 Thread:Thread Group的执行单元;[numthreads(x, y, z)]; 单个Thread Group中的Thread数为x * y * z,左上角为(0,0,0),右为X轴正方形,下为Y轴正方向,Z表示阵列厚度; SV_GroupThreadID:组内线程坐标;Thread在自己的Thread Group中的坐标; SV_DispatchThreadID:Thread在所有Thread中的坐标;可以理解为将一个长方体切成a * b * c份,每一份再切成x * y * z份,某个Thread在这个类似于坐标系的长方体中也可以用三维坐标表示:SV_DispatchThreadID = (x,y,z) * SV_GroupID + SV_GroupThreadID。 SV_GroupIndex:Thread所在的Thread Group的Index;排序方式为从每一页的左上角开始,右数至末端后从下一排左端开始,右数至最后一排时从下一页开始。 ▲CS语法 CS语法和Shader语法有很多类似之处,读者应熟练掌握Shader语法后再尝试CS语法。 Kernel声明: #pragma kernel KernelFunction 类似于Shader的Pass中定义vertex、geometry、fragment,这里的kernel声明了一个GPU任务(Kernel)的名称并指定了执行方法,在C#脚本中对Kernel的Dispatch会直接执行这个函数。 Kernel的ID:根据定义先后顺序,0,1…进行赋值。 包含声明: #include “SimplexNoise3D.hlsl” 这个完全和Shader语法一致。 变量声明: RWStructuredBuffer
▲GPU结构与变量存储 SP(streaming processor):最基本的处理单元,可执行一个Thread;图中绿色框框(Core);一个SM中根据不同构架包含100个左右的SP,硬件上分为多个warp。 warp:调度和运行的基本单元,比如图中32个SP组成一个区块,所有Thread执行相同指令,可以空闲。 SM(streaming multiprocessor):GPU大核,比如一个GPU有16个SM。 Register:与SP相对的存储区域,存储函数内引用的本地变量,离SP最近,访问速度最快,以4byte为单位构成。 Shared Memory:与SM相对的存储区域,与L1缓冲一同被管理 Global Memory on DRAM:在DRAM中,容量很大,访问速度相对慢。 local memory:在DRAM中,存储Register中装不下的数据。 texture memory:将Global Memory作为texture的专用存储区域。 constant memory:读取专用存储区域,预先保存Kernel的引数和定数。 registers(Read-write per-thread) local memory(Read-write per-thread) shared memory(Read-write per-block) global memory(Read-write per-grid) constant memory(Read-only per-grid) texture memory(Read-only per-grid) ▲HLSL编程指南 很多细节是没法在书中展开的,需要仔细阅读微软的HLSL编程指南。 ▲Variable Syntax变量声明语法 HLSL变量类似于C语言,变量有一些命名限制,根据变量声明的位置决定了变量的作用域属性,可以将user metadata附加到变量。HLSL中有几种标准数据类型,也定义了C语言中没有的额外类型,以帮助优化4元矩阵计算。
[Storage_Class] [Type_Modifier] Type Name[Index] [: Semantic] [: Packoffset] [: Register];
Storage_Class 提示编译器 extern: 将全局变量标记为着色器的外部输入;这是所有全局变量的默认标记。 nointerpolation: 将vertex shader的outputs传递给pixel shader时,不进行差值。 precise: shared: groupshared: 变量存储于thread-group-shared memory,DX10中最多16kb,DX11中最多32kb。 在对groupshared变量进行写入时,多Threads之间没有同步,所以这意味着每个Thread只有对groupshared数组变量的部分区域的写入权限。使用SV_GroupIndex以保证多Threads之间不会发生冲突。在读取方面,所有Threads都有对数组的读取权限。 static: 标记一个local变量为static,初始化一次,在函数调用之间保持值不变。如果声明中没有初始化则值设置为0. uniform: 标记一个变量,在shader执行过程中其数据为恒量。 global变量默认为uniform。 volatile: 标记一个变量,这个变量频繁变更,提示编辑器将变量作为local变量。 Type_Modifier const row_major column_major:默认值 Type 变量类型 参考HLSL Data Types。 float/float4 name = {0,0,1,1} int/int name[3] = {1,2,3} Name[Index] 使用字符串作为shader变量的唯一标识。 定义数组类型变量时,Index表示数组长度。 Semantic 可选,参数的用法信息,用于连接到shader的输入/输出。 有几种预定义的Semantic供vertex/pixel shader使用。 Packoffset 可选关键字,Packing Rules for Constant Variables。 Register 可选关键字,将shader变量手动分配到指定Register。 Initial_Value 可选的初始值,值的数量应与声明匹配。 extern类型global变量必须初始化为a literal value(字面意思值?)。 static类型变量必须初始化为常量。 全局变量没标记为static或extern时,不会被编译到shader。 编译器不会自动设置全局变量的默认值,不会在优化中使用全局变量。