如何根据GPU Tier动态降级后处理
解读
国内项目上线前必须通过腾讯WeTest/字节跳动云真机的GPU分级测试,iOS分3档(A8以下、A9-A11、A12+),Android按Mali-G、Adreno、PowerVR系列再细分为Tier1(低端720p)、Tier2(中端1080p)、Tier3(高端2K+)。策划和运营要求“画质拉满”做卖点,但低端机一旦低于25 fps就会被应用商店评为“性能差”,直接损失30%自然量。因此面试官想确认两点:
- 你能否在引擎层实时拿到准确的GPU Tier;
- 你能否用零GC、零Shader变体爆炸的方式把后处理管线“降级”而不重启游戏。
知识点
- SystemInfo.graphicsDeviceName/graphicsMemorySize/vendor 的坑:国内山寨机篡改GPU字符串,必须再跑一遍自定义Benchmark(渲染16张RT、执行5次Blit,统计GPU耗时)校准Tier。
- Unity Scriptable Render Pipeline(URP) 的Volume Framework优先级:Camera → Global → Local,运行时可通过VolumeProfile.Replace<VolumeComponent>() 动态替换,但注意URP 14+以后VolumeManager.instance.stack.Reload() 会触发C#到C++同步,主线程卡顿1-2帧,必须提前异步预加载AssetReference<VolumeProfile>。
- CommandBuffer.SetGlobalFloat 与Shader Keyword的性能差异:Keyword会产生ShaderVariant,低端机内存占用+15%,推荐用Branching Multi_compile__ 空keyword,用uniform float _QualityStep 在Shader内做静态分支(if _QualityStep < 0.5),因为Mali-G52对动态分支开销极低。
- 后处理降维策略:
- Bloom:高阶用Dual Kawase 13 tap,中阶4 tap,低阶直接Bloom OFF并合并到ToneMapping LUT;
- DOF:高阶Full-res COC + Bokeh Texture,中阶Half-res Tile-base,低阶Fake DOF用radial blur;
- SSAO:高阶HBAO 8 steps + temporal,中阶GTAO 4 steps,低阶** baked AO lerp**;
- MotionBlur:高阶Tile-base Velocity,中阶Camera Velocity,低阶关闭;
- ColorGrading:高阶ACES 3D LUT 32^3,中阶2D LUT 256^2,低阶Fast Reinhard。
- 热更新兼容性:若项目用HybridCLR,VolumeProfile不能放在Resources,必须打Addressable并标记为CanChangePostProcessing分组,否则il2cpp stripping会把未引用组件裁掉,导致低端机运行时MissingReferenceException。
答案
我在项目中把GPU Tier检测封装成GpuTierManager,启动场景异步Benchmark 1秒,输出Tier1/2/3枚举,然后:
- 创建PostProcessQualitySettings ScriptableObject,预先配好三套VolumeProfile(High/Mid/Low),用VolumeComponent的CreateInstance<ClonedVolumeComponent> 避免直接改原始Profile;
- 在URP RenderPipelineManager.beginCameraRendering 回调里,根据当前TierReplace< Bloom >、< ColorAdjustments > 等组件,不调用Reload(),而是volume.isGlobal = true 直接覆盖;
- 对Bloom等需要降采样的特效,用CommandBuffer.SetGlobalFloat("_BloomDownSample", tier==1?4:2) 在Shader里做静态分支,确保零Keyword;
- 低端机关闭MotionBlur、SSAO后,把省下的GPU Bandwidth转给UI Overdraw,保证帧率≥30的同时发热≤45℃(腾讯PerfDog验收标准)。
上线后小米Redmi 9A从18 fps提升到32 fps,iPhone 6发热降低4.3℃,用户差评率下降1.2%。
拓展思考
- 可变分辨率+后处理联动:低端机可把RenderScale降到0.8,但Bloom阈值需线性补偿(_BloomThreshold = 0.80.8),否则画面发灰;
- DLSS/FSR 国内手游尚未普及,但Unity 2023 URP 16已支持Spatial Upscaler,可让Tier1跑540p→1080p,后处理仍在540p空间做,节省40% GPU Time;
- Vulkan Subpass 在Mali-G710上可把Depth→Color 后处理合并为0 ms开销,但Adreno 530驱动有Bug,需运行时检测GPU型号再决定是否开启;
- 未来项目可让策划在Excel里填“后处理权重分”,程序运行时做背包算法自动组合最优特效包,实现千人千面的QoS。