# WebGPU

## 背景

当前微信小游戏平台以 `webgl/webgl2` 作为主要渲染上下文，其 API 基于 OpenGL ES 设计，已难以满足高品质小游戏对渲染能力与性能的需求。

随着图形技术全面进入 Vulkan、Metal、Direct3D 12 等现代图形 API 时代，W3C 推出了新一代 Web 图形标准 WebGPU，主流浏览器与游戏引擎均已陆续支持。微信小游戏平台顺应这一趋势，正式提供 WebGPU 渲染能力。

## 性能优势与技术原理

相比 WebGL，WebGPU 主要具备以下优势：

- **Compute Shader**：支持通用 GPU 计算，可将粒子模拟、骨骼蒙皮、场景剔除等并行任务转移到 GPU 执行。
- **Indirect Draw**：绘制参数可由 GPU 直接生成，配合 Compute Shader 实现 GPU Driven 渲染管线。
- **更低的渲染提交开销**：通过预编译管线状态、资源绑定组和命令缓冲批量提交，大幅降低 Draw Call 的 CPU 开销。
- **先进渲染特性**：支持 WGSL 着色语言、Storage Buffer、存储纹理等现代渲染能力。

### 性能收益

|  项目   |  优化效果 |  备注 | 
|  ----  | ----  | ----  |
| 帧耗时  | **降低 5% ～ 20%** | 视游戏复杂度而定 |

## 准备工作

### 1. 特别提示

+ WebGPU 目前仅支持在Android下运行，iOS与鸿蒙正在建设中，将在不久后推出。
+ 建议游戏 **充分验证后** 再进行发布。

### 2. 运行环境要求

+ **微信版本要求**：需 **>= 8.0.79**。
+ **基础库版本要求**：需 **>= 3.17.3**。
+ **Android 系统要求**：需 **>= 10.0**。

开发阶段建议尽可能使用高版本的微信。

## 能力支持与限制

微信小游戏WebGPU API对标标准Web用法，细节处可能存在差异，请参考以下内容。

### 1. 获取 WebGPU

通过 `wx.getGPU()` 获取 GPU 对象，当前环境不支持 WebGPU 时返回 `undefined`，开发者可据此降级到 WebGL。

```js
const gpu = wx.getGPU();
if (!gpu) {
  // 降级到 WebGL
}
const adapter = await gpu.requestAdapter();
const device = await adapter.requestDevice();
const context = canvas.getContext('webgpu');
context.configure({ device, format: gpu.getPreferredCanvasFormat() });
```

### 2. 注册错误回调

通过 `device.addEventListener('uncapturederror', (event) => { ... })` 注册错误回调，当设备出现validation error时，会触发此回调。**请注意，注册该回调有一定性能开销，建议仅在调试时使用。**

```js
device.addEventListener('uncapturederror', (event) => {
  console.error(event.error);
});
```

### 3. 能力支持

+ **着色语言**：仅支持 WGSL，不支持 SPIR-V、GLSL。
+ **Features**：以设备实际上报为准，请通过 `adapter.features` 查询后按需使用。
+ **Limits**：以 `adapter.limits` 为准。

### 4. 已知限制

+ device 须在 `context.configure({ device })` 之后才可使用，请勿在此之前创建资源。
+ `canvas.getContext('webgpu')`与 `canvas.getContext('webgl')` 不能同时使用，否则会返回空值。
+ 暂不支持多渲染目标（MRT），仅 `colorAttachments[0]` 生效。
+ 暂不支持 `createRenderPipelineAsync`、`createComputePipelineAsync`、`importExternalTexture`、`timestampWrites`。
+ 仅支持单个 device，`requestDevice` 的 `requiredFeatures`、`requiredLimits` 暂不生效。
+ `popErrorScope` 恒返回 `null`，错误监控请使用 `uncapturederror` 事件；错误对象不支持 `instanceof`，请通过 `error.name` 判断类型。

## 接入方式

### Laya 引擎

选择支持 WebGPU 的引擎版本（建议使用最新版本），按照 Laya 官方文档打包发布为微信小游戏即可。

### 团结引擎快适配方案

团结引擎 **1.11.0** 及以上版本支持 WebGPU，需配合快适配插件的 WebGPU 分支使用：

```
https://github.com/wechat-miniprogram/minigame-tuanjie-transform-sdk.git#feat-webgpu
```

### Unity 引擎

Unity 引擎暂不提供 WebGPU 支持，如有需要，请[联系小助手](https://res8.wxqcloud.qq.com.cn/wxdoc/0d0a621f-a50f-4a89-8454-2ef762b4fbf0.png)。

### 其他引擎

1. **JS 项目**：通过 `wx.getGPU()` 获取 GPU 对象后，即可按照 Web 标准调用 WebGPU API，使用方式详见上方「能力支持与限制」，完整示例可参考 [WebGPU 小游戏示例](https://git.weixin.qq.com/wechat-minigame/wagame-webgpu-samples)。
2. **C++ 项目**：推荐使用平台提供的 [wxWebGPU C++ SDK](https://git.weixin.qq.com/wechat-minigame/webgpu_cpp_sdk)，在 WASM 内直接编码渲染指令，性能优于 JS 调用方式。详细接入配置及示例工程（三角形、纹理、阴影、Compute 粒子、压缩纹理等）请参考 SDK 仓库文档。

## 常见问题 Q&A

### Q1. 为什么开启了 WebGPU 后，性能更差了？比如单帧耗时更大了。
A1. WebGPU 主要降低的是 CPU 侧的渲染提交开销，并不能保证在所有场景下都优于 WebGL，实际优化效果与项目的具体用法密切相关。建议从以下几个方面排查：
+ **是否为 GPU 瓶颈**：WebGPU 项目通常更容易出现 GPU 瓶颈（GPU Bound）。此时 CPU 侧的优化收益有限，建议优先排查分辨率、Overdraw、Shader 复杂度、后处理等 GPU 负载。
+ **设备性能差异**：根据测试，WebGPU 在越高端的设备上表现越好，中低端设备上的收益可能不明显。
+ **用法是否合理**：建议复用 Pipeline、BindGroup 等对象，避免每帧重复创建资源。
+ **是否注册了错误回调**：uncaptured error会降低性能，建议在发布时关闭。

如排查后仍有问题，请联系我们一起进行排查。

### Q2. 为什么开启 WebGPU 模式后，渲染异常了？
A2. 微信小游戏的 WebGPU 能力仍在持续完善中，部分接口行为可能与 Web 标准存在差异，可先参考上方「能力支持与限制」进行确认。建议先在浏览器环境中验证渲染表现是否正常，若浏览器中表现正常而微信小游戏中出现异常，请联系我们一起进行排查。

## 联系我们

如有任何问题，欢迎[联系小助手](https://res8.wxqcloud.qq.com.cn/wxdoc/0d0a621f-a50f-4a89-8454-2ef762b4fbf0.png)咨询。
