⚡ Compute Shader 移动端深度指南
📚 1. 理论基础 (Theoretical Basis)
1.1 核心定义
- GPGPU (General-Purpose computing on Graphics Processing Units): 利用 GPU 强大的并行计算能力处理非图形渲染任务。
- Compute Shader: 一种独立于渲染管线(不经过顶点/片元着色器)的 Shader 程序,用于通用计算。
- 线程模型:
- Thread: 最小执行单元。
- Group: 线程组,包含多个线程(如 8x8x1)。组内线程共享 Thread Group Shared Memory (TGSM)。
- Dispatch: CPU 发起的调度指令,指定执行多少个 Group。
1.2 移动端支持现状 (Mobile Support)
- API 要求:
- OpenGL ES 3.1+: Android 5.0+ 基本都支持。
- Metal: iOS (A7芯片以上) 完全支持。
- Vulkan: Android 7.0+ 支持。
- 兼容性陷阱:
- Mali GPU (部分旧型号): 对浮点精度支持不佳,可能导致计算结果与 PC 不一致。
- 最大线程组限制: 移动端通常限制每个 Group 最大线程数为 256 或 512,而 PC 通常是 1024。安全做法是使用 64 (8x8) 或 128。
- 读写限制: 旧设备可能不支持对同一纹理的随机读写 (UAV),需使用 Ping-Pong Buffer 技术。
🛠️ 2. 实践应用 (Practical Implementation)
2.1 Vampirefall 适配场景
-
海量弹幕计算 (Bullet Hell):
- CPU 无法处理 5000+ 弹幕的位移和碰撞。
- 方案: Compute Shader 计算位置 ->
AppendStructuredBuffer存储结果 ->DrawMeshInstancedIndirect渲染。
-
流场生成 (Flow Field):
- 地图格子 100x100,每帧更新。
- 方案: 一个 Kernel 计算所有格子的向量,性能比 C# Job System 快 10-50 倍。
2.2 核心代码结构 (Unity HLSL & C#)
HLSL (MyCompute.compute)
C# (ComputeController.cs)
2.3 性能注意事项 (Performance Tips)
- 数据传输瓶颈: 最忌讳 每帧在 CPU 和 GPU 之间来回拷贝数据 (
GetData/SetData)。- 正确做法: 数据常驻 GPU,渲染时直接用
Graphics.DrawMeshInstancedIndirect读取 Buffer。
- 正确做法: 数据常驻 GPU,渲染时直接用
- 异步回读 (AsyncGPUReadback): 如果必须把结果拿回 CPU(例如判断怪物是否死亡以播放音效),必须使用
AsyncGPUReadback.Request,否则会卡死主线程等待 GPU 完成。
🌟 3. 业界优秀案例 (Industry Best Practices)
3.1 Dyson Sphere Program (戴森球计划)
- 机制: 戴森球壳面上数万个节点的旋转和能量传输。
- 实现: 纯 GPU 模拟。只有在玩家点击查看详情时,才异步回读少量数据到 CPU。
- 借鉴: 视觉表现层(弹幕、特效粒子)应完全脱离 CPU 逻辑。
3.2 Genshin Impact (原神) - 移动端体积云
- 机制: 动态天气和体积云。
- 实现: 使用 Compute Shader 进行 3D 噪声采样和光照计算。
- 优化: 采用了半分辨率渲染 (Half-Resolution) 和时域重投影 (Temporal Reprojection) 来降低移动端负载。
🔗 4. 参考资料 (References)
- 📄 Unity Manual: Compute Shaders
- 📄 Catlike Coding: Compute Shaders Tutorial - 入门必读
- 📺 GDC 2019: Mobile Compute Shaders in Fortnite
- 🌐 Mobile GPU Compatibility: Android Developer Guide