Unity Compute Shader入门指南
创作时间:
作者:
@小白创作中心
Unity Compute Shader入门指南
引用
CSDN
1.
https://blog.csdn.net/yx314636922/article/details/136654305
Compute Shader是Unity中用于GPU通用计算的重要工具,它允许开发者直接利用GPU的并行计算能力来处理各种计算任务。本文将从GPU计算的基本原理出发,详细介绍Compute Shader的定义、优势和限制,并通过具体的代码示例展示如何在Unity中创建和使用Compute Shader。
一、原理概念
早期的GPU计算中,顶点着色和片元着色完全独立,顶点着色器不能读取纹理,开发者需要按照算力分配VS和FS的复杂度来保证效率,并且图形还需要经过一系列图形管线处理。如下图。
不过随着非图形计算的需求增大,出现了GPGPU(General Purpose GPU,GPU通用计算)业务场景,图形硬件开始引入一种统一的计算单元来处理vertex和pixel,不需要经过图形流水线而是直接用GPU并行计算。如下图,顶点着色和片元着色合并为“compute units”处理。【也有更复杂的内存系统】
- GPU包含很多compute units,每个compute unit又包含了:
- 若干SIMD units((single instruction multiple data)),由它们来实际执行指令
- 每个SIMD unit可以对多个elements进行同一个操作
- 每个compute unit内部包含了一些local memory,可以用于不同shader stages之间的通信
实现这种计算的Shader,就是Compute Shader。
主要优势:
- 利用GPU的compute units实现高效并行计算
- 比vertex-frag的方式能更快交换数据,减少CPU bottleneck,避免使用昂贵的多Pass,灵活性更高
- 语义可以在图形、空间外
限制性:
- 不是所有效果都适合用compute shader,比如传统fs里做的很多简单后处理,用其反而降低效率
- 有些GPU架构缺少特定硬件,导致需要针对性设计、兼容
- 难开箱即用,需要不断测试优化
为了编写高效的compute shader,应该:
- 把一个大问题分成尽可能多的若干独立的work items,分得越多越好
- 尽量使用uniform变量,速度快,内存小
- 如果代码需要频繁访问内存,应当尽可能减少状态保存
- 一个线程组内避免使用分支
- 将for循环指令拆开
二、Unity Compute Shader
2.1 Compute Shader格式、参数含义
在Unity的中右键-Create-Shader-Compute Shader创建,后缀为 .compute 。
//声明kernel的函数名,至少有一个,可以定义预处理宏
#pragma kernel CSMain
#pragma kernel KernelOne SOME_DEFINE DEFINE_WITH_VALUE=1337
#pragma kernel KernelTwo OTHER_DEFINE
// 可读写(Read和Write)二维纹理,直接Result[uint2(0,0)]来访问,rgba对应数据类型为float4
//官方除此以外还有RWBuffer和RWStructuredBuffer,见https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-rwtexture2d
RWTexture2D<float4> Result;
//定义一个线程组(Thread Group)中可以被执行的线程(Thread)总数量,即为X*Y*Z
//其值与Dispatch中设置的核函数numthreads对应
[numthreads(8,8,1)]
//SV_GroupID:线程组id,int3;如果Dispatch(1024 / 8,1024 / 8,1),也就是定义了一个128 * 128个线程组,SV_GroupID的范围(0, 0, 0) - (128, 128, 0)
//SV_GroupThreadID:线程组里线程的id,int3
//SV_DispatchThreadID:全局id,图片每个像素的坐标,int3;例如一个线程组有(X,Y,Z)个线程,SV_GroupID=(a,b,c)的线程组里的SV_GroupThreadID=(i,j,k)的线程的SV_DispatchThreadID为:(a*X+i, b*Y+j, c*Z+k)
//SV_GroupIndex:int,线程组内的某个线程的下标,(8里边的第几个),假如有(X,Y,Z)个线程,第一个线程(0,0,0)=0,(1,0,0)=1,(1,0,0)=2,...,(0,1,0)=X,...,(0,0,1)=X*Y
void CSMain (uint3 groupId : SV_GroupID,
uint3 groupThreadId : SV_GroupThreadID,
uint3 id : SV_DispatchThreadID,
uint groupIndex : SV_GroupIndex)
{
Result[id.xy] = float4(id.x & id.y, (id.x & 15)/15.0, (id.y & 15)/15.0, 0.0);
}
2.2 调用
普通shader直接在材质上使用即可,compute shader还需要在C#文件中专门调用才能使用。
public class testCompute : MonoBehaviour
{
private RenderTexture texture;
public ComputeShader computeShader;
public Material material;
private int kernal;
void Start()
{
texture = new RenderTexture(256, 256, 16);
texture.enableRandomWrite = true;
texture.Create();
kernal = computeShader.FindKernel("CSMain");
material.SetTexture("_BaseMap", texture);
}
void Update()
{
computeShader.SetTexture(kernal, "Result", texture);
computeShader.Dispatch(kernal, 256 / 8, 256 / 8, 1);
}
}
默认效果:
热门推荐
云梦县的文化瑰宝——睡虎地秦简
椰子汁+白米饭:食物中毒后快速恢复的绝妙组合!
碳酸氢钙:食品界的隐形守护者?
碳酸氢钙:宝宝食品的秘密武器?
从杭州大兜到舟山三毛祖居:一场跨越时空的文化之旅
四川成都市磅礴的城市规划,和周边县级市对比,究竟达到何种程度
新生代导演如何引领香港电影新潮流?
成都二日游攻略:从宽窄巷子到大熊猫基地,深度体验蓉城魅力
三亚出行交通工具攻略
天坛健身大爷的社交圈:运动让生活更精彩
职场宝妈如何玩转社交媒体,打造高效人脉圈?
在烤箱中制作完美香脆培根所需的一切材料
智慧养殖:自动化技术如何全方位提升食品安全?
舌尖上的三亚——八大特色美食,让您回味无穷,看看你都吃过吗?
维生素B1缺乏,如何自查与补救?
维生素B1缺乏,如何自查与补救?
维生素B1的功效与作用
湛江水上运动:乘风破浪,扬帆起航
湛江最美海岸线探秘:三座海岛的绝美风光
震颤的症状及可能原因
手抖科普:揭示震颤背后的秘密
糖尿病患者食用荸荠指南:科学控糖,健康饮食
秋冬控糖有妙招:全谷物、豆类和油性鱼的健康饮食指南
糖尿病患者的冬季养生秘籍:吃荸荠有讲究!
5个适合初学者的腿部锻炼动作,让双腿更加强壮
昆虫学联手植物学!创新“图谱”让互作双方同时呈现
徐克新作《黄飞鸿》:经典重现,创新不止
《龙虎武师》:揭秘香港武侠片黄金时代的幕后英雄
胡金铨经典武侠片中的艺术设计揭秘
福州上下杭:非遗文化盛宴点亮新春