UPL9-17——Compute Shader

本章代码关键字

1
2
3
ComputeShader                    // ComputeShader类,可以关联计算Shader资源
computeShader.FindKernel() // 查找computeShader某个kernel函数的索引,需要传入函数名,通过索引去执行入口函数
computeShader.Dispatch() // 传入要执行的kernel函数的索引,同时传入xyz线程组,线程组传入数量和kernel函数声明的线程组的线程数量有关

Compute Shader

Compute Shader (计算着色器) 是让 GPU 帮你算东西的程序,是一种在 GPU 上运行的 通用计算程序
属于 GPGPU(通用 GPU 计算 —— General-Purpose GPU Computing)的一部分
它的核心目标是:让开发者脱离渲染管线,直接利用 GPU 的并行计算能力来处理计算任何类型的数据

举例说明

  • CPU 像一个聪明的人,会处理复杂的逻辑(比如“写策划案”)
  • GPU 像一大群工人,擅长干重复、独立的活(比如“拧螺丝”)

Compute Shader 就是告诉这群 GPU 工人:
每个人负责一个任务,大家一起干,干完告诉我结果,比如:
我们想要计算一个 512 * 512 的图片,每个像素的颜色要变化一点
CPU 一次只能处理一个像素,要一个一个像素依次处理
GPU 有几千个核心,可以一次处理几千个像素

因此,Compute Shader 就相当于是写给 GPU 的批量计算脚本,让 GPU 帮助我们批量的计算

注意:Compute Shader 不像普通 Shader,它不依赖渲染管线,主要就是用来处理计算的
普通 Shader 是用来渲染画图的,Compute Shader 是用来计算数据的

Compute Shader 的应用其实横跨了很多知识体系,比如:

  1. 图形学知识
  2. 并行计算
  3. 数学与算法
  4. 引擎整合
  5. Shader 开发

等等

现在学习的知识,只是掌握了对 Compute Shader 的基础认知
知道它的工作原理,知道它的基本使用,具体如何应用它,还有很多路要走

你可以认为 Compute Shader 其实并不是 Shader 的补充模块,而是一个独立的并行计算体系!是前端程序员进阶必须要学习的内容!

Compute Shader 的基本结构

  1. 创建 Compute Shader 文件

    在 Project 窗口 右键 Create —> Shader —> Compute Shader
    创建的文件后缀为 .compute,属于 HLSL 风格代码

    image

  2. Compute Shader 文件 基本结构

    1. 声明入口函数
    2. 声明输入输出资源
    3. 声明每个线程组内的线程数量
    4. 声明入口函数类型
    5. 书写核心计算逻辑
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 1. 声明入口函数
    #pragma kernel CSMain

    // 2. 声明输入输出资源
    RWTexture2D<float4> Result;

    [numthreads(8,8,1)] // 3. 声明每个线程组内线程数量
    // 4. 声明入口函数类型
    void CSMain (uint3 id : SV_DispatchThreadID)
    {
    // 5. 书写核心计算逻辑
    Result[id.xy] = float4(id.x & id.y, (id.x & 15)/15.0, (id.y & 15)/15.0, 0.0);
    }

C# 调用 Compute Shader

  1. 在 C# 代码中找到对应的 ComputeShader 文件,可以声明 ComputeShader 类型公开变量,然后在 Inspector 处关联对象,或者动态加载
  2. 利用 API 找到入口函数索引 computeShader.FindKernel()
  3. 传递相关参数 computeShader.SetXXX()​(不同类型参数调用不同的 Set 方法)
  4. 启动计算 computeShader.Dispatch(入口函数索引, x线程组数, y线程组数, z线程组数)
  5. 使用 GPU 计算完成输出的数据渲染或者传回 CPU
  6. 释放资源

注意:Dispatch() 函数的调用类似异步,不会对 CPU 造成阻塞

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using UnityEngine;

public class Lesson92 : MonoBehaviour
{
public ComputeShader computeShader; // 声明 computeShader 变量,可以通过 Inspector 窗口关联,也可以动态加载

void Start()
{
int index = computeShader.FindKernel("CSMain"); // 获取 computeShader 中名为 CSMain 的函数索引
computeShader.SetFloat("f", 10.0f); // 传递相关参数
computeShader.Dispatch(index, 64, 64, 0); // 启动计算
// 使用GPU计算完成输出的数据渲染或者传回CPU
// 释放资源
}
}

Compute Shader 相关

  • 多个入口函数
  • 数据类型
  • 数据输入规则
  • 组内线程数量
  • 参数的系统语义
  • 获取 GPU 数据
  • 常用 API
  • 应用场景