并行渲染介绍

介绍并行渲染

线程概述

最初,渲染器运行在渲染线程中,游戏线程将该线程的命令排队,以便稍后在帧中运行。这些命令会调用渲染硬件接口(RHI)层,它是受支持的平台上不同图形API的跨平台接口。

为了提高此过程的效率并利用受支持的平台的功能,渲染线程现在作为一个前端,将不受平台限制的图形命令排入渲染器的命令列表,然后新的RHI线程通过后端的相应图形API转换(执行)这些命令。借助这种分离,可在支持它的平台(例如游戏机、DX12和Vulkan)上实现独立的后端并行化。一般来说,在前端并行生成的任何内容都会在后端并行转换。

某些命令可在不使用命令列表系统的情况下执行,例如锁定和解锁操作。这些命令由渲染线程直接发出。在这些情况下,引擎要么转储清除RHI线程并等待操作完成,要么复制数据并对其进行排队。实现方式根据根据操作和平台的不同而异。

图形命令和命令列表

渲染线程排队的命令是从 FRHICommand 模板衍生的结构体的实例。这些命令覆盖在转换过程中调用的 Execute 函数,并存储所需的任何数据。根据不同平台的最佳性能的启发法,可在平台上以不同方式将命令提交给GPU(例如,每帧提交多次,在帧结束时一次提交等),或者也可通过发出 FRHISubmitCommandsHint 命令来提交。

平移中使用的主要接口是 IRHICommandContext。每个平台和API都有一个衍生的 RHICommandContext。在平移期间,系统向 RHICommandList 提供了 RHICommandContext 以用于操作,并且每个命令的 Execute 函数都调用 RHICommandContext API。命令的上下文负责执行给定操作所需的状态阴影、验证和任何特定于API的细节。

同步

GameThread、RenderThread、RHI Thread和GPU之间的渲染器同步是一个非常复杂的主题。简而言之,虚幻引擎4通常配置为"后一帧(single frame behind)"渲染器。这意味着当RenderThread处理第N帧时GameThread处理第N + 1帧,除非RenderThread的运行速度比GameThread快。添加RHI线程使同步过程更为复杂化,因为当RHI线程处理第N帧时,RenderThread能够通过完成第N+1帧的可视性计算而移动到RHI线程之前。最终结果是,当GameThread处理第N+1帧时,RenderThread可以处理第N帧或第N+1帧的命令,RHI线程也可以平移第N帧或第N+1帧的命令,具体取决于执行时间。这些保证由 FFrameEndSync 和名为 RHIThreadFenceFRHICommandListImmediate 函数仲裁。它还可以保证,无论并行化的配置方式如何,向GPU提交命令的顺序与在单线程渲染器中提交命令的顺序相同。这可以确保一致性,如果更改渲染代码,必须保持顺序不变。

调试

控制此行为的控制台变量有多种。由于这些阶段中的许多阶段是互不相关的,可在测试中将它们单独禁用,并在时间允许的情况下分阶段启动新平台。例如

命令

说明

r.rhicmdusedeferredcontexts

如果设置为0,将禁用后端的并行化。默认值为 1。

r.rhicmduseparallelalgorithms

如果设置为0,将禁用前端的并行化。默认值为 1。

r.rhithread.enable

如果设置为0,将完全禁用RHI线程。命令列表仍将生成,但它们在某些点将直接在渲染线程上进行转换。

r.rhicmdbypass

如果设置为1,将完全禁用命令列表生成并使渲染器的行为与原来一样,直接在没有命令列表的情况下调用渲染线程上的RHI命令。请注意,除非禁用RHI线程,否则将忽略此项。

Parallel_Rendering_00.png

显示并行命令列表生成在Unreal Engine中的工作原理。

欢迎帮助改进虚幻引擎文档!请告诉我们该如何更好地为您服务。
填写问卷调查
取消