MAKE · WRITE · SHARE

Base-RHI线程与多线程命令录制

GPU 很快也可能等不到足够的工作。渲染系统如果在一个 CPU 线程里完成可见性、Draw 组织和 API 命令生成,提交侧就可能先成为瓶颈。

多线程录制把命令准备分给多个工作线程,但并不改变 GPU 上真实的数据依赖。理解 RHI(Rendering Hardware Interface,渲染硬件接口)线程模型,必须把 CPU 任务、命令列表与 GPU 执行三个时间轴分开。

CPU 并行录制命令,提交顺序仍遵守 GPU 的资源依赖

1. 渲染线程与 RHI 各自做什么

一个常见模型中,游戏线程更新世界,渲染线程生成供渲染使用的数据和绘制计划,RHI 层把这些计划映射到图形 API。具体阶段能否合并或并行,由引擎与后端决定。

经典引擎也可以跨帧流水,不能把 Game→Render→RHI→GPU 一串箭头解释为“旧模型每帧完全串行”。队列中的帧数、同步点和任务粒度决定实际等待。

2. 并行录制与并行执行

两个线程可以分别录制 A、B 的命令,即使 B 在 GPU 上必须读取 A 的结果。CPU 录制只是在描述工作,录制完成的先后不自动成为正确的 GPU 执行顺序。

提交侧仍要根据依赖决定命令列表顺序、资源状态与同步。RenderGraph 可以提供这种关系,但它并不意味着只有没有资源依赖的 Pass 才能在 CPU 并行录制。

3. 每个工作线程需要独立可写状态

命令分配器、命令列表和临时描述符分配区,通常要按 API 的线程安全规则独立使用。不能多个线程同时写同一个录制对象,再希望内部锁免费处理竞争。

还要避免共享全局“当前材质”“当前资源状态”被并发修改。常见办法是为任务准备不可变输入与局部状态,汇总时统一解析资源状态边界。

4. 任务怎样切分

按 Pass、绘制批或可见列表块划分都可以。粒度太粗会让少数线程拖尾,太细则调度、分配和合并成本上升。

1
2
3
4
5
准备共享只读数据
→ 多个工作任务分别生成命令列表
→ 等待必要录制完成
→ 解析状态与执行依赖
→ 按计划提交 GPU 队列

降低锁竞争之外,还应关注数据局部性、缓存行共享和临时分配。不断为小 Draw 分配对象,可能让多核忙于管理而不是生成有效命令。

5. 显式 API 没有消除驱动成本

D3D12/Vulkan 提供更明确的资源和提交控制,但应用需要承担更多生命周期与同步责任。D3D11 也存在延迟上下文等录制机制,不能说旧 API 完全不允许多线程。

PSO 准备、描述符管理、资源创建和命令提交仍有成本。把 API 换掉,不会自动解决 Draw 数量、材质碎片化或糟糕任务划分。

6. 怎样测量收益

先确认 Render/RHI 侧确实限制帧吞吐,再比较录制总时间、最长任务、等待和提交次数。平均 CPU 利用率升高,不等于帧时间下降。

还要观察 GPU 是否更连续,以及在途帧数是否增加了输入延迟。通过增加排队换取吞吐,应明确其体验代价,不能只报告 FPS。

总结

多线程命令录制优化的是 CPU 准备路径,正确提交依赖仍需单独维护。独立可写状态、合理粒度和明确资源生命周期,比单纯增加线程数更决定系统是否有效。

参考资料