一项令人心动的新能力--GPU Resident Drawer,它可以帮助降低复杂场景的绘制功耗,提升复杂场景的渲染性能。通过优化CPU侧的负载,它使得开发者能在保证性能的前提下,制作出场景更加复杂且效果出众的小游戏。这一能力也同时会让iOS、Android等平台有一定的受益。

GPU Resident Drawer 是如何工作的?

  • 利用BatchRendererGroup进行快速合批(渲染场景常驻GPU,减少渲染参数提交)

  • 更好的利用GPU Instancing,减少draw call调用

从而降低 CPU 负载并提升帧率。

关键特性

  • 使用传统GameObject + Renderer组织的场景,可自动获取BatchRendererGroup的高效合批,无需对现有场景进行特殊改造

  • Draw call数量越高、场景越复杂、场景中可GPU实例化的Renderer越多,收益越大

  • Renderer更新频率越低(如位置、材质变化等),需要更新GPU数据的频率越低,收益越大

  • 优化对象是MeshRenderer。不包括SkinnedMeshRenderer、VFX、粒子等

 支持小游戏平台

在 Unity 6的版本里,GPU Resident Drawer 不支持GLES平台。为了优化小游戏CPU侧绘制功耗,借鉴了Unity 6的思路,定制了针对小游戏平台的GPU Resident Drawer。

  • 针对小游戏不支持SSBO和Compute Shader的限制,使用Texture存储Renderer数据。

  • 针对小游戏平台暂不支持Burst和多线程、C#中的计算开销高于C++的问题,全新实现了一份纯C++版本,以保证性能表现。

在后续的版本中,将针对iOS、Android以及PC平台做更好的适配及优化。

                                  GRD 带来的性能收益

GPU Resident Drawer适用于有大量Renderer共享相同的Mesh和 Material的场景,比如建筑、岩石、草地等。

如视频所示,URP Sample Scene中的Garden场景开启GPU Resident Drawer后:Batches由3000以上降低至1000以下、FPS由120以下提升到140以上。

从Profiler/Timeline中也可以看到明显的耗时下降。

                                           安卓平台,Garden场景,关闭GRD

                                        小游戏平台,某MMO游戏,关闭GRD

                                        小游戏平台,某MMO游戏,开启GRD

开发者能观察到的性能提升,取决于场景的规模和渲染时GPU实例化的程度,GPU实例化对象越多,获得的收益就越大。

开启GPU Resident Drawer的收益同样体现在功耗指标的降低,在多个平台和设备上,我们可以看到功耗数据的喜人变化。

小游戏平台,以某款重度MMO小游戏为例:

安卓和iOS平台,以Garden场景为例:

*需要注意的是,在少数旧型号设备上(例如骁龙870),开启GPU Resident Drawer后也可能出现一定的功耗负收益(约100mW),可能和硬件、驱动的支持不完善有关,建议开发者根据实际测试数据权衡选用。

                                           快速上手

GPU Resident Drawer 功能适用于URP 3D项目,您可以通过以下几个步骤快速启用:

1.打开菜单 Edit > Project Settings > Quality, 双击 Render Pipeline Asset,在inspector中配置渲染管线。

2.在渲染管线配置界面,Rending 一栏中,将 GPU Resident Drawer 设置为 Instanced Drawing

3.在渲染管线配置界面,启用 SRP Batcher

4.在渲染管线配置界面,双击Renderer List,配置Renderer,如下:Rendering Path 设置为 Forward+ 或 Forward(Forward 仅支持单个平行光源

5.打开菜单 Edit > Project Settings > Graphics, 在 Shader Stripping 部分,将 BatchRendererGroup Variants 设置为 Keep All,以确保编译所有必要的着色器变体

您还可以继续优化设置、局部禁用 GRD 功能、查看优化效果、排查问题等,更多操作请参阅官方指南:

团结引擎 - 手册: GPU Resident Drawer

                                           Known issues

  • 目前仅支持 URP 管线,未来将增加对 HDRP 管线的支持。

  • 如果在 RenderFeature 里有增加 Material Override Mode 的材质,且材质本身不支持 GPU Resident Drawer(使用自定义shader且实现不满足要求,例如未声明dots_instancing keyword等),这种情况下 Override 的材质可能无法正确的显示。

  • 在 Editor 打包成功后可能会出现场景不渲染,并在控制台输出错误日志的情况,这个时候 reload 场景或者 reload project 即可以恢复正常,Player 模式不受影响。

  • 引擎会根据 GPU Resident Drawer 开关对 Shader 变体进行裁剪,以减少其数量。因此,在 Player 中动态开关 GPU Resident Drawer 时,可能会因找不到变体而导致渲染错误。可以修改 Package 源码,手动移除 Shader 变体裁剪的逻辑代码。

  • Forward 路径下灯光目前只支持单一主方向光。

  • SpeedTree 的物体暂时不支持Wind的效果,开启 Wind 后物体会回退到 GRD Disable 的渲染状态

  • 在 Android 手机上使用 Vulkan,打 development 包调试时,会报 Platform does not support uploading texture2d subrect data 这个错误,但 release包不受影响。

性能优化

在 URP 管线中,采用 SRP Batcher 可以减少渲染状态的切换,提高渲染效率:

分析 SRP Batcher 的过程,我们发现有两个环节可以优化:

  • Renderer 信息常驻 GPU Buffer:收集当前场景中所有符合条件的MeshRenderer,将绘制相关数据保存至 GPU Buffer 中,收集到的这些MeshRenderer  不再每帧生成 RenderNode。

  • GPU Instancing:组织 Batch 时,将相同材质的 Renderer 组织到同一个 Batch,对于Mesh也相同的Renderer,通过 GPU Instancing 绘制从而减少 Draw Call 调用。

GRD针对这两个环节都进行了优化:

  • Renderer 信息常驻 GPU Buffer:收集当前场景中所有符合条件的MeshRenderer,将绘制相关数据保存至 GPU Buffer 中,收集到的这些MeshRenderer  不再每帧生成 RenderNode。

  • GPU Instancing:组织 Batch 时,将相同材质的 Renderer 组织到同一个 Batch,对于Mesh也相同的Renderer,通过 GPU Instancing 绘制从而减少 Draw Call 调用。

Logo

分享前沿Unity技术干货和开发经验,精彩的Unity活动和社区相关信息

更多推荐