WebGPU 不等于工程大模型自动变快:真正决定性能的是数据与调度

2 阅读4分钟

把渲染器从 WebGL 换成 WebGPU,不代表同一个大场景会自动变快。WebGPU 提供了更明确的资源管理、更现代的渲染与计算接口,但应用如何组织对象、材质、缓冲区和每帧更新,仍然决定最终性能。

Three.js 官方 issue 中就有一个很直观的例子:场景包含大量未批处理 Mesh 时,WebGPURenderer 的表现可能低于 WebGLRenderer。维护者的讨论也把问题指向 per-object uniform/UBO 更新和大量 render item 带来的开销,而不是简单归因于浏览器没有开启 GPU。参考:The performance of the WebGPU Renderer is much slower than WebGL

这件事对工程模型尤其重要,因为 BIM、机械装配和工厂模型天然包含大量构件。一个源文件可能有数万甚至更多对象,每个对象又有自己的材质、变换、可见性和业务身份。如果把源结构原样映射成“一个构件一个 Mesh、每帧逐个更新”,换 API 不能消除对象级管理成本。

先把性能问题拆成五层

1. 数据准备

RVT、NWD、STEP、JT、CATIA 等源工程格式不是浏览器运行时格式。它们包含 B-Rep、装配关系、实例、属性和单位。第一次解析时应生成面向查看的分块几何、材质资源、结构属性索引和稳定对象身份;后续打开复用缓存。

如果每次打开都在浏览器重新解析完整源文件,渲染 API 还没有开始工作,CPU 和内存就可能已经成为瓶颈。

2. 对象与批次

减少 Draw Call 很重要,但“把所有东西合成一个 Mesh”不是通用答案。合并粒度过大后,视锥裁剪、局部隐藏、构件选择、LOD 和按需释放都会失效。

更实用的组合是:

  • 重复零件共享几何和材质;
  • 可实例化的对象使用实例化;
  • 静态小对象按材质和空间形成合理批次;
  • 批次内部仍保留从 GPU 结果回到工程构件 ID 的映射。

3. 可见性与工作集

工程大模型不应该全量常驻 GPU。相机当前能看到什么、接下来可能看到什么、哪些构件正在被选择或审阅,决定本帧工作集。

分块、LOD、视锥裁剪、遮挡、请求优先级和资源回收需要形成同一套调度策略。否则只是更快地把无关数据上传到显存。

4. 每帧状态变化

大量对象的矩阵、材质参数或可见性每帧变化,会造成 buffer 更新、绑定和状态切换。WebGPU 能提供更底层的控制,但应用仍需把变化聚合为紧凑数据:

  • 把可见性、选择、高亮等状态放进结构化 GPU buffer;
  • 只更新真正变化的范围;
  • 避免遍历整棵场景树同步状态;
  • 将静态资源与动态状态分离。

5. 交互与对象身份

大模型查看器不能为了批处理丢掉构件身份。结构树、属性、拾取、隐藏、测量、剖切和业务台账必须指向同一对象。

因此优化目标不是“Mesh 数最少”,而是“在可控批次内保留稳定身份,并让 GPU 和业务层都能高效访问”。这也是普通 Three.js Demo 与工程模型产品之间最容易被低估的差异。

测试时不要只看平均 FPS

至少分别记录:

  • 首次源格式转换时间;
  • 缓存后的再次打开时间;
  • 首屏可交互时间;
  • 相机快速移动时的帧时间和资源请求;
  • 结构树选择、隐藏、剖切时的长任务;
  • CPU 内存、GPU 显存和资源回收后的稳定值。

平均 FPS 很高但第一次交互冻结两秒,或者浏览十分钟后显存持续上涨,都不能算稳定的大模型体验。

工程化路线

我们做 ModelView 时,把 WebGPU 放在完整链路的一层:源格式首次转换后生成可复用缓存,运行时再通过分块、LOD、按需加载和 GPU 调度控制工作集,同时保持结构树、属性、选择和协同状态的对象身份。

性能口径也必须把条件说完整:模型完成首次转换并生成缓存后,亿级三角面模型可以在 5 秒内再次打开并进入可交互视图,浏览和审阅过程保持满帧渲染。这里不是把首次 RVT、STEP 等源文件转换时间算成 5 秒。

说明一下,我是 ModelView 的开发者。Windows 标准版可以直接下载并用自己的真实模型测试;如果项目需要企业内网、在线平台、界面工具或业务接口定制,也可以在现有引擎上继续开发:

gitee.com/onedraw/mod…