rain_sxr头像
关注
移动端 TBDR 架构深度剖析:Tile 内存溢出与 Resolve 开销消除封面图

移动端 TBDR 架构深度剖析:Tile 内存溢出与 Resolve 开销消除

移动端 TBDR 架构深度剖析:Tile 内存溢出与 Resolve 开销消除

封面信息图

在移动端做渲染性能优化时,许多习惯了桌面端 GPU(IMR,即时渲染架构)的开发者常会陷入一个误区:认为只要 DrawCall 降下来、着色器指令数少,游戏帧率就会稳定。然而,当把游戏部署到真实手机(如搭载 Mali 或 Adreno GPU)并使用 Snapdragon Profiler 或 Arm Mobile Studio 抓包时,却发现外部显存带宽(External Memory Bandwidth)长期处于红色告警状态,伴随着手机剧烈发热与降频。

这种性能崩溃的根源,在于没有针对移动端主流的 TBDR(Tile-Based Deferred Rendering,基于图块的延迟渲染)架构 进行管线适配。

[桌面端 IMR (Immediate Mode)]
顶点着色 ──> 光栅化 ──> 片段着色 ──(每个像素直接读写系统显存 VRAM)──> 极高显存带宽消耗

[移动端 TBDR (Tile-Based Deferred Rendering)]
1. Binning Pass: 顶点着色 ──> 计算图元所属 Tile ──> 写入 Parameter Buffer (系统内存)
2. Rendering Pass: 针对每个 16x16 / 32x32 图块:
   - 从片上高速 SRAM (Tile Memory) 载入数据
   - 在片上高速完成深度测试、遮挡剔除 (HSR/FPK)、片段着色与混合
   - 一次性将最终颜色 Resolve 写回系统 DRAM

TBDR 的片上内存(On-Chip SRAM)红利与代价

移动设备没有独立显卡和高带宽 GDDR 显存,GPU 与 CPU 共享极度受限且耗电的 LPDDR 系统内存。为了解决带宽瓶颈,TBDR 在 GPU 核心内部集成了极小(通常每个核心仅几十 KB 到几百 KB)但速度极快(TByte/s 级别)的片上 SRAM(Tile Memory)。

  • 红利:在单个 Tile(例如 16×16 像素)内部进行的 Depth Testing、Alpha Blending、甚至 4x MSAA 采样,全部在片上 SRAM 中发生,完全不消耗外部 DRAM 带宽。
  • 代价:渲染流程必须被一分为二,几何数据必须在 Binning 阶段进行预分桶,且不同 RenderPass 之间的切换需要谨慎管理 Tile 内存与系统 DRAM 的数据交换(Load / Store 操作)。

痛点一:Parameter Buffer 溢出与几何膨胀

在第一阶段(Binning/Tiling),GPU 必须将所有绘制图元的顶点变换结果以及 Tile 索引列表存放在系统内存中的 Parameter Buffer(参数缓冲区) 中。

如果场景中存在以下极端情况:

  • 美术资产未做 LOD,同屏堆叠了数百万面微小三角形(Sub-pixel Triangles);
  • 粒子特效发射了数万个密集的微小 Quad 面片;
  • 大量图元跨越了多个 Tile 边界,导致 Tile 引用列表暴增。

此时 Parameter Buffer 将迅速耗尽预分配的物理内存空间,迫使 GPU 驱动将部分 Tile 刷写回系统内存并触发二次分块(Tiling Fallback),引发严重的 GPU 停顿(Stall)和内存抖动。

防御准则:严格控制移动端同屏绘制顶点数(通常控制在 30万~50万 以内),并启用 GPU 几何视锥体裁剪与遮挡剔除,避免微小三角形跨图块泛滥。

痛点二:Load / Store Action 误配引发的带宽雪崩

在 Vulkan、Metal 以及 Unity URP / 自研管线中,每一个 RenderPass 都有明确的输入载入操作(Load Action)和输出保存操作(Store Action)。

如果在开始渲染一个全新帧或全屏覆盖的 Pass 时,错误地将深度或颜色缓冲区的 Load Action 设置为了 Load(或 Clear 以外的操作),GPU 就必须将上一帧或系统 DRAM 中的全尺寸纹理数据逐字节重新读入片上 SRAM;同理,若在 Pass 结束时将只在当前 Pass 内部使用的临时深度缓冲区设置为了 Store,GPU 又必须将整张深度图写回 DRAM。

错误的 RenderPass 配置:
[DRAM] ──(无意义 Load: 读取 1080p 深度 8MB)──> [Tile SRAM] ──(绘制)──> [DRAM] ──(无意义 Store: 写入 1080p 深度 8MB)
整帧累计数十个 Pass,瞬间产生数 GB/s 的纯浪费带宽!

现代图形 API 零带宽 RenderPass 配置规范

在 Vulkan 中,必须通过精确配置 VkAttachmentDescription 来消除无意义的带宽交互:

// Vulkan RenderPass 附件优化配置
VkAttachmentDescription colorAttachment{};
colorAttachment.format = VK_FORMAT_R8G8B8A8_UNORM;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
// 1. 开始时直接清除,绝不从 DRAM 载入历史数据
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
// 2. 结束时写回 DRAM 供后续呈现
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;

VkAttachmentDescription depthAttachment{};
depthAttachment.format = VK_FORMAT_D24_UNORM_S8_UINT;
depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
// 3. 关键优化:若后续不需要采样深度图,深度缓冲在 Pass 结束后直接丢弃,严禁 Store!
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

在 Unity URP / Custom SRP 中,应通过 ConfigureTarget 与 ConfigureClear 明确指定:

public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
    // 指定 Color 写入,Depth 仅在片上使用并在结束时丢弃 (DontCare)
    ConfigureTarget(colorAttachmentHandle, depthAttachmentHandle);
    ConfigureClear(ClearFlag.All, Color.black);
}

public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
    var cmd = CommandBufferPool.Get("CustomPass");
    // 执行渲染逻辑...
    context.ExecuteCommandBuffer(cmd);
    CommandBufferPool.Release(cmd);
}

移动端延迟着色(Deferred)的最佳实践:Subpass 与片上直通

在传统桌面端延迟渲染中,管线先将 Albedo、Normal、Roughness 等属性写入多张 G-Buffer 纹理(Store 到显存),再在 Lighting Pass 中重新作为 Texture 采样(Load 到显存)。这种方式在移动端是绝对的灾难。

在 TBDR 架构上,必须利用 Vulkan Subpass(在 Metal 中对应 Programmable Blending / Imageblocks,在 OpenGL ES 中对应 EXT_shader_pixel_local_storage):

  • G-Buffer 的写入与 Lighting Pass 的读取全部在 同一个 RenderPass 的不同 Subpass 中完成。
  • G-Buffer 数据在片上 SRAM 中直接流转,完全无需写回系统 DRAM。
  • 深度与 G-Buffer 附件在 Pass 结束时全部标记为 DONT_CARE,实现移动端“零外部带宽开销”的真正延迟着色。

通过深刻理解 TBDR 的硬件流动模型,将几何面数克制在合理区间,并以严苛的标准治理每一个 Pass 的 Load/Store 行为,即可从根本上压制移动端显存带宽,消除发热降频,让高画质渲染管线在移动设备上稳定运行。

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/rain_sxr/article/details/165278685

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--