解释Half Resolution与Dual Kawase Blur的优化思路
解读
国内Unity项目面试中,这道题常被用来快速判断候选人对移动端GPU带宽瓶颈与后处理管线设计的理解深度。面试官想听的不是“把分辨率砍一半”这种表面答案,而是:
- 为什么半分辨率能省采样带宽与ALU;
- Dual Kawase Blur怎样把传统高斯模糊O(n²)复杂度降到O(log n)并天然适配半分辨率;
- 在U3D里如何落地:RenderFeature怎么拆Pass、怎么与Unity的RTHandle系统配合做自动scale、自动回收,以及怎么在ShaderLab里用Branch做Early-Exit防止Overdraw;
- 最终如何把耗时从8 ms压到1.5 ms以内,让低端骁龙665也能跑满30 FPS。
知识点
- GPU带宽公式:带宽≈分辨率×每像素字节数×(读+写次数);半分辨率直接×0.25。
- Kawase Blur核心:分离卷积→双线性采样一次取4邻域→迭代步长指数递增→四次迭代等效64 tap高斯。
- Dual Kawase优化:Down→Up两条金字塔,Down阶段每级双线性降采样并做3×3 Kawase,Up阶段反向重建,利用half resolution RT做bilinear upsample减少cache miss。
- Unity实现细节:
- 用Rendering.RenderPassInput的**ConfigureInput(ScriptableRenderPassInput.Color)**告诉URP不要额外申请全屏RT;
- 用**RTHandles.Alloc(scaleFactor)**动态申请0.5×RT,避免常驻显存;
- 在Blit时设置RenderBufferLoadAction.DontCare省一次读;
- 用**#pragma multi_compile _ _USE_HALF_RES**在Shader里做条件编译,防止低端机Fallback全分辨率。
- 常见坑:半分辨率+Alpha通道带透明物体时会出现边缘重影,需要在Down Sample前做一次Alpha预乘并关闭sRGB Read/Write防止色偏。
答案
“Half Resolution的核心是把后处理RT的宽高各砍一半,GPU带宽直接降到25%,同时片元着色器执行次数也减到四分之一,对千元机非常有效。
Dual Kawase Blur在此基础上再做算法级优化:
- 先降采样到半分辨率,用双线性采样一次取4邻域,做一次3×3 Kawase,迭代4次,等效64 tap高斯,复杂度从O(n²)降到O(log n)。
- 升采样阶段用同样的Kawase核反向重建,利用bilinear upsample把半分辨率结果插值回全屏,视觉损失几乎不可见。
- 在Unity里我封装成CustomRenderPassFeature,用RTHandleSystem动态申请0.5×RT,RenderPassEvent.AfterRenderingTransparents插入,CommandBuffer.SetRenderTarget时把LoadAction设成DontCare省一次读,整体耗时从8 ms降到1.2 ms,在骁龙665上跑《XX项目》30 FPS稳定。
- 为了防透明物体边缘重影,我在Down Sample前加了一次Alpha预乘并关闭sRGB,最终UI Bloom效果与全分辨率PSNR>48 dB,策划验收通过。”
拓展思考
- 如果项目需要4K输出,可以把Dual Kawase改成Quarter Resolution+Temporal Stabilization,用Motion Vector做重投影,FSR做锐化,带宽再降75%,但需解决鬼影与闪烁。
- 在URP 16的Rendering Debugger里打开Frame Timing,可以看到半分辨率RT的cache miss rate比全分辨率低60%,这是Dual Kawase在Mali-G52上比传统Two-Pass Gaussian快3倍的底层原因。
- 未来Vulkan Subpass+Fragment Shading Rate可以把半分辨率Dual Kawase做到0.8 ms以内,但Unity 2022 LTS还不支持,需要改Custom SRP并手动写VkSubpassDescription,风险较高,建议等Unity 6000 LTS官方支持。