Base-RHI线程与多线程命令录制
GPU 很快也可能等不到足够的工作。渲染系统如果在一个 CPU 线程里完成可见性、Draw 组织和 API 命令生成,提交侧就可能先成为瓶颈。
多线程录制把命令准备分给多个工作线程,但并不改变 GPU 上真实的数据依赖。理解 RHI(Rendering Hardware Interface,渲染硬件接口)线程模型,必须把 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 | |
降低锁竞争之外,还应关注数据局部性、缓存行共享和临时分配。不断为小 Draw 分配对象,可能让多核忙于管理而不是生成有效命令。
5. 显式 API 没有消除驱动成本
D3D12/Vulkan 提供更明确的资源和提交控制,但应用需要承担更多生命周期与同步责任。D3D11 也存在延迟上下文等录制机制,不能说旧 API 完全不允许多线程。
PSO 准备、描述符管理、资源创建和命令提交仍有成本。把 API 换掉,不会自动解决 Draw 数量、材质碎片化或糟糕任务划分。
6. 怎样测量收益
先确认 Render/RHI 侧确实限制帧吞吐,再比较录制总时间、最长任务、等待和提交次数。平均 CPU 利用率升高,不等于帧时间下降。
还要观察 GPU 是否更连续,以及在途帧数是否增加了输入延迟。通过增加排队换取吞吐,应明确其体验代价,不能只报告 FPS。
总结
多线程命令录制优化的是 CPU 准备路径,正确提交依赖仍需单独维护。独立可写状态、合理粒度和明确资源生命周期,比单纯增加线程数更决定系统是否有效。