UE高级性能剖析技术(1)-- RHI线程(渲染提交)

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

在最前面

基于UE的手游客户端的性能主要由这七大部分构成:CPU逻辑,CPU渲染,图形API(提交),GPU渲染,内存,带宽,加载时间。这几个基本元素又会合力衍生出一些新的性能指标,例如功耗(往往同gpu负载和带宽紧密相关)。同时这七部分又构成一个闭合的木桶,最长的一块是主要瓶颈,并且瓶颈可以在这几块转移流动。作为开发者我们解决性能问题的步骤一般都是按照做性能剖析,解读结果,定位问题,增加剖析代码,优化问题,重复剖析的迭代过程来执行。而高效准确详细的对性能进行剖析得到结果是第一步,在任何引擎上,只要我们能做到在任意时刻准确的获取想要的性能剖析结果,那么才会胸有成竹不会慌,该系列文章将归纳总结在ue下对每一性能指标的剖析方法,做深入分析,我们需要工具的帮助,也需要程序员理解引擎并知道如何去编写合适的剖析代码。

 

最近刚好做过一轮RHI线程的剖析,第一篇就从RHI开始,我会坚持把后面几篇写下去。

 

渲染API瓶颈

渲染API瓶颈是3D手游的常见瓶颈,我们常说的drawcall 过多了,卡渲染就是指的卡在这里,其实这个卡渲染卡的是cpu。为什么drawcall会卡,因为cpu需要通过对渲染api的调用来驱动gpu做事情,1个drawcall的背后是一堆渲染api的调用,下面是一个常见的drawcall过程,

 

可以看到为了一次绘制(1个drawcall),要设置shader,创建buffer等等,这些相比最后的draw那一步来说都是相对更费时的。

当测试反馈给我们卡drawcall的时候,作为程序我们需要一种手段来衡量出确切的当前做哪些drawcall,或者说绘制哪些东西更耗,最好是精确到耗在绘制哪个模型的哪个api调用上,我们才能真正的给美术予以优化指导。

UE中精确定位RHI瓶颈

在UE中,pc和android平台通常渲染api的调用会放在一个单独的线程,叫做RHI线程,这个线程专门负责渲染指令的提交,即调用显卡的API。我们分析渲染提交的卡顿就是要分析这个RHI线程。

多线程渲染工作模型

但是RHI线程不是单独存在的,它需要同game,render线程协作,rhi的卡顿可能不只是rhi的卡顿,首先需要清楚UE里面RHI线程和其他线程的工作模式:

 

 

这里面game render rhi gpu分别在4个并行的工作线上,有这样几个特点:

  1. game thread最多可以等渲染一帧,也就是说渲染如果第N帧的渲染在第N+1帧的game tick结束时还没有完成,那么渲染就会把game卡住,render 和rhi不会有帧延迟。
  2. game是render和rhi的源驱动者,game的卡顿可能会卡住渲染
  3. render 负责产生drawcall,rhi负责提交drawcall,因此render的卡顿也可能卡住rhi提交。
  4. 渲染的最后一步要swapbuffer,即等待gpu完成,所以gpu的卡顿也可能会卡住rhi。
  5. 除了gamethread本身,render  rhi 和gpu的工作都是存在间隙的,即game逻辑喂给渲染任务的时机会影响渲染工作的密度,也会影响到渲染的时间,小量多次会浪费渲染效率。

 

UE中rhi的瓶颈的来源

现在我们知道rhi的卡顿可能来自于以下几种情况:

a RHI指令自身的卡顿,即通常所说的卡drawcall,过多的dc,过多的渲染状态切换,过多的渲染资源创建,等等;

b game或者render thread的卡顿

c gpu的卡顿。

 

对于情况b,我们可以通过UE的status 看当前的game和render的线程执行时间来容易的判断出来,来排除是rhi上出了问题。

对于情况c, UE的status中在rhi线程上会统计一个叫做swapbuffer的时间,如果这个时间过长,那么就是gpu瓶颈了。

 

真正比较麻烦的是定位情况a,即对于rhi指令本身的卡顿瓶颈。对于这种情况UE自带的stat工具通常不能给出比较有力的分析结果,自带的方法只能统计一帧在rhi上做几种给定操作的时间,但是在复杂的线程条件下,有时很难确定这些卡顿的幕后原因,有时rhi问题只是一个表象,为了得到rhi线程瓶颈的确切原因,我们至少要能够明确以下几个事情:

 

1 Rhi线程的执行是由一堆有序的rhi command组成的,我们要能捕捉到具体的那一个rhi command的执行时间比较长,比如是创建场景中哪个房子的vb?

2 是在render thread的哪一个步骤塞入的渲染数据导致了这个rhi command执行的时间比较长,是在渲染阴影的时候,还是渲染basepass,还是做遮挡剔除?

3 是在game thread的哪一个步骤塞入的渲染数据导致了这个rhi command执行的时间比较长?是在加载场景?还是在绘制UI的时候?

 

笔者在项目中遇到过一个问题,在一些低端机,rhi会有时突然卡顿几秒以上,看stat文件如下:

我只能看到在rhi 线程的thcikbegin阶段发生了巨大的卡顿,然后就没有细节了,不知道是具体哪个rhicommand,然后看gamethread在wait,也不知道是game thread的哪一步触发了这个rhi瓶颈。我们需要一些办法。

 

定位UE中rhi线程的瓶颈

我们需要分别将上面三种原因捕捉到,就能解开这个问题。

首先定义一个宏,只有我们需要捕捉这些详细的rhi瓶颈时开启,因为这些操作会存在较大的overhead。

 

定位具体rhicommand的时间

对于rhi command的具体执行时间,我在FRHICommand的最终执行阶段ExecuteAndDestruct中创建一个FScopeCycleCounter,counter的名字就直接rtti当前command的typename。

有时候我们需要更细节的知道这个command除了类型外的信息,例如如果这是一个createvb的command,那么vb的原始模型名字是什么,vb大小等,我在一些command处额外传了一些debug用的string,然后在这些command的执行前补上一个FScopeCycleCounter。这样我们就能拿到精确到具体rhicommand的提交耗时了。经过这个补充,我能拿到这样的rhi 线程执行时间统计:

这样谜底就清晰了很多,原来这时候存在大量的vb创建,数了一下,有几百个,在同一帧内几百个vb的创建,在低端android上会产生5秒钟的超级卡顿,那么问题来了,为何在这一帧会同时产生这么多的vb卡顿,是game或者render 上发生了什么事情,如果我们查看当前的game thread ,它显示的是wait,是不知道原因的,因为game ,render ,rhi是分开工作的,我们现在rhi处于瓶颈已经不是事故的”第一现场”了,我们需要进一步让你发生在第一现场。

 

定位在render的哪个阶段发生了rhi的瓶颈

UE的rhicommandlist自带了一个函数FRHICommandListImmediate::SetCurrentStat,可以用来让render给rhi加一个标记,这个标记就可以认为是render的某个阶段的名字,UE自带了在render 的很多阶段下了这个标记,我们还可以自己补充,这个函数的原理如下:

 

这个status本身也是以command的形式插入队列,所以每一条rhi执行的cmd会被统计到它之前最近的那个status tag下面,通过不断的细分插入这些tag,我们可以跟踪到rhi的cmd从是在render的哪个阶段被产生。需要注意的是这个tag只能在render thread里插入。我为render thread补充了一些细化的tag后,如前面的图,我发现这个大量的vb创建发生在渲染线程的一帧渲染结束到下一帧渲染开始之前,在这个阶段有game 逻辑往render 里面堆入了大量创建vb的指令,所以问题还要继续往game thread 上找”第一现场”。

 

定位在Game的哪个阶段产生RHI瓶颈

其实我们仍然可以模仿renderthread一样在game thread上给rhi的command list里面插入tag,但是有个问题,renderthread是一种相对简单的render command的队列的顺序执行, tag量有限相对容易操作,但是game thread里面逻辑极其复杂,我们希望可以复用game thread上面已经埋好的一些scope counter,不过game和rhi是两条并行的thread,需要在我们关心的scope处让二者能够强行同步住,才能容易的使用game 自己的scope counter抓住rhi的执行。我们这样去实现,假设下面是我们关心的一个game thread的区段,在前后加上代码如下

#if STAT_RHI_ADVANCED

FlushRenderingCommands(true)

   DECLARE_SCOPE_CYCLE_COUNTER(TEXT("XXX "), STAT_XXX, STATGROUP_RHI_GAME_SYNC);

#endif

  //game 代码段

    …

    …

//

#if STAT_RHI_ ADVANCED

     FlushRenderingCommands(true);

#endif

 

FlushRenderingCommands(true)的意思是在这个位置强制将所有当前的rhicommand执行完毕,阻塞住当前线程,所以上面这个代码段的原有的XXX统计的时间将包括这段时间内因为game thread上发生的渲染事件的渲染而花费的时间。

 

通过在game thread的主要逻辑处,插入这些同步rhi线程的代码,当rhi线程发生瓶颈的时候,我们只要查看当前gamethread在哪里停住(wait event),就可以判断是什么game 逻辑导致了rhi线程的瓶颈。有了这个机制,我们接着截stat文件,会看到当rhi处于巨大瓶颈时,game thread停在了这里:

凶手被抓住了,是一个资源正在被缓存池预加载!

这个奇怪的rhi上的卡顿的真正原因其实是game 线程上在加载一个模型资源!如果只依靠ue本来的stat分析,是无论如何都不可能猜到这个幕后的凶手的。

 

那么问题来了,一个资源的加载为何会导致海量的vb同时创建?通过进一步的分析代码,会发现因为这里用的是同步加载,而UE的同步加载的机制,是创建一个加载任务堆到同异步加载一样的加载队列里,因为不能保证依赖关系,所以要等待当前所有队列中的任务完成才能继续下去,也就是说当前的同步加载的时间绝不仅仅是加载完你要的这个模型而已,他需要将当前异步加载任务在队列中的所有资源加载完!而这个时候恰恰处于场景在level streaming的阶段,最后发现此事加载队列中的资源上百个,这个同步加载遇上level streaming的结果就是,在这一帧要完成上百个模型的创建,模型的postload会初始化rhi资源,导致一帧内大量vb的创建,卡死rhi,所以罪魁祸首是同步加载,同步加载将level streaming的过程也强行同步了,找到了问题,我们就可以通过相关的优化手段来排除这个瓶颈。

 

RHI上的问题可能往往不只是rhi上的问题那么简单,通过上面说的一些方法我们可以清楚的看到各种rhi上瓶颈的真正原因。

 

虚幻引擎之多线程渲染机制 虚幻引擎之多线程渲染机制 文章目录虚幻引擎之多线程渲染机制一、前言二、游戏线程渲染线程的交互2.1 ENQUEUE_RENDER_COMMAND宏2.2 渲染线程2.3 数据交互2.3.1 数据更新2.3.2 创建渲染器2.3.3 触发渲染管线2.4 同步三、渲染线程RHI线程3.1 RHI线程的创建3.2 RHI的任务参考文章 一、前言 在 虚幻引擎编程基础(二) 中,笔者简单地介绍了虚幻引擎中的多线程的类型,共分为三类: 标准多线程实现FRunnable; 使用线程池的AsyncTask; Tas 阅读详情

相关推荐

Unreal引擎性能分析及优化

虚幻引擎包含了很多工具和功能,能帮助开发者测试并优化应用程序,以便达到目标帧率和高质量的体验

yaoyutian的博客 2800

Performance - UE4里的性能分析和优化

对《虚幻独立开发日2019:UE4里的性能分析和优化》的摘抄和笔记,归档发表; UE4里的性能分析和优化: 优化相关工作越早越好; 优化首先判断的是GPU还是CPU的性能瓶颈: stat unit命令显示每帧的渲染时间; 在性能评估时,尽量避免在编辑器里进行性能分析,最好在实际的运行平台上做调试;如果是开发PC游戏,必须在编辑器中调试的时候,也记得在Stand alone模式下运行(还有具体注意事项见上图); 以上各个线程是并行运行的,但又依赖上一个线程的计算结果; Game线.

GT的虚幻引擎文档 2596

深入解析虚幻引擎多线程渲染的数据同步机制

本文深入探讨了虚幻引擎中多线程渲染的数据同步机制,详细解析了游戏线程渲染线程的协作基础、ENQUEUE_RENDER_COMMAND的工作原理以及高级同步控制模式。通过双缓冲数据架构和智能指针等技术,确保线程安全与性能优化,特别适合游戏开发者和图形程序员提升渲染效率。

weixin_29017445的博客 206

剖析虚幻渲染体系(13)- RHI补充篇:现代图形API之奥义与指南

剖析虚幻渲染体系

ttod的博客 1223

基于UE4的多RHI线程实现

1 UE4的现有多线程架构 UE的多线程渲染结构如下图, 它有几个特点 game thread 负责逻辑tick,render thread 负责culling、batching和draw api的生成, rhithread 负责drawapi的执行 game和render两个线程最多可以差一帧,即前后两帧的gam额和render可以并发,通过Fframeendsync做同步 render 和rhi之间的关系是帧内的合作关系,即不能达到前后两帧render和rhi的并发,前一帧的drawapi最多在下一帧

leon 7590

腾讯游戏学院专家:UE高级性能剖析技术RHI

https://www.fgba.net/sitemap.xml

august5291的博客 1135

深度解析Unreal Engine渲染线程RHI线程协作机制

在现代游戏引擎中,多线程渲染架构是提升性能的关键技术。其核心原理是通过线程间的职责分离,实现CPU与GPU工作负载的并行化处理。游戏线程负责逻辑与状态收集,渲染线程负责指令翻译与命令生成,RHI线程则专注于底层图形API调用。这种设计的技术价值在于最大化硬件利用率,减少CPU等待时间,从而提升帧率与渲染效率。在Unreal Engine中,这一架构通过ENQUEUE_RENDER_COMMAND宏与FRHICommand系统实现,广泛应用于复杂场景渲染、动态资源更新及高性能渲染管线定制等场景。理解游戏线程

weixin_30466039的博客 356

UE5性能分析实战:Stat命令与RHI工具精准定位渲染瓶颈

在游戏开发与实时图形应用中,性能优化是保障流畅体验的核心环节。其原理在于通过量化分析,定位CPU与GPU的任务负载瓶颈,从而实施针对性优化。这项技术的核心价值在于将主观的“卡顿”感受转化为可测量的数据指标,显著提升项目的可维护性与跨平台适配能力。应用场景广泛覆盖从移动端到3A大作的各类UE5项目,尤其在处理复杂场景渲染、高负载材质与大规模Draw Call时至关重要。本文聚焦于UE5引擎内置的Stat命令与RHI工具,它们如同性能诊断的“仪表盘”与“X光机”,能有效分析GPU渲染管线与定位材质性能热点,是解

weixin_27890975的博客 290

UE4 GameClient源码剖析:从架构到性能优化的核心技术解析

在游戏开发与实时交互应用领域,理解客户端底层架构是提升应用性能与稳定性的关键。客户端作为连接用户操作与系统响应的核心枢纽,其运行机制涉及输入处理、逻辑运算、资源管理与渲染输出等多个子系统的高效协同。通过剖析其源码,开发者能够深入掌握从事件捕获、数据流转向多线程渲染协同的全链路原理,这对于构建高响应、低延迟的交互体验具有重要技术价值。尤其在需要处理海量数据或复杂场景的应用中,如数字孪生与大数据可视化,对客户端内存管理、资源流送及网络同步机制的深度优化,直接决定了最终用户体验的流畅度与实时性。本文以UE4引擎为

weixin_34387468的博客 780

UE5多线程渲染实战:如何用ENQUEUE_RENDER_COMMAND优化你的游戏性能

本文深入探讨UE5多线程渲染优化技术,重点解析ENQUEUE_RENDER_COMMAND机制在提升游戏性能中的关键作用。通过详细讲解渲染线程架构、命令批处理技术线程同步最佳实践,帮助开发者实现帧率稳定提升,适用于虚幻引擎5的高性能游戏开发场景。

weixin_29021291的博客 257

UE5粒子系统渲染管线深度解析:从绘制路径164到性能优化实战

在实时渲染领域,粒子系统是实现火焰、烟雾、魔法等视觉特效的核心技术。其基本原理是通过大量微小的图元(如精灵、网格)模拟群体行为,创造出复杂的动态视觉效果。从技术实现上看,现代游戏引擎普遍采用实例化渲染来高效处理海量粒子,其核心价值在于以极低的绘制调用开销驱动数百万个粒子的实时渲染。在虚幻引擎5(UE5)中,粒子渲染被集成到其高度优化的渲染管线内,通常通过特定的绘制路径(如路径164)进行调度,该路径专为动态实例化绘制而优化,涉及从游戏线程数据准备、渲染线程命令生成到GPU执行的完整流水线。理解这一管线对于解

weixin_28077113的博客 261

UE5多线程渲染优化:ENQUEUE_RENDER_COMMAND原理与实战指南

在游戏开发中,多线程渲染是提升性能的关键技术,它通过将CPU计算与GPU绘制解耦,实现并行处理以突破帧率瓶颈。其核心原理基于生产者-消费者模型,游戏线程生成渲染指令,渲染线程异步执行,从而避免线程阻塞。这项技术的工程价值在于能够充分利用现代硬件多核能力,显著提升复杂场景下的渲染效率。在UE5引擎中,ENQUEUE_RENDER_COMMAND宏是实现线程安全通信的核心工具,它允许开发者将渲染相关操作安全地投递到渲染线程。典型应用场景包括动态纹理更新、自定义RHI绘制指令提交以及渲染资源生命周期管理。通过合理

weixin_33747129的博客 384

剖析虚幻渲染体系(11- RDG

剖析虚幻渲染体系

ttod的博客 1961

Unreal Insights性能分析实战:从渲染管线到线程瓶颈优化

性能分析是游戏开发中的核心环节,它通过追踪程序运行时的各项指标,帮助开发者定位性能瓶颈。其原理在于对CPU、GPU、内存等硬件资源的监控与数据采集,形成可视化时间线。在虚幻引擎项目中,Unreal Insights作为官方性能分析套件,能够以极细粒度记录引擎运行时事件,包括游戏线程逻辑、渲染指令提交、GPU通信等。对于采用延迟渲染管线的UE5项目,Insights可以清晰展示BasePass、光照计算、半透明渲染等阶段耗时,帮助开发者识别过度绘制、复杂着色器或光源过多等问题。同时,针对常见的CPU端性能问题

weixin_33700350的博客 424

C++与虚幻引擎开发:从核心架构到性能优化的实战指南

C++作为高性能系统编程语言,以其对硬件的直接控制能力和卓越的运行效率,成为游戏引擎与核心逻辑开发的基石。其原理在于通过手动内存管理、编译时优化和底层硬件访问,为实时交互应用提供稳定的性能保障。在游戏开发领域,这种技术价值尤为突出,它解决了大规模场景渲染、复杂物理模拟与高频逻辑更新中的性能瓶颈问题。虚幻引擎作为行业领先的实时3D创作平台,其完整的工具链和可视化脚本系统(蓝图)极大地提升了开发效率。然而,要充分发挥引擎潜力,实现高度定制化的游戏玩法(如复杂的技能系统、AI行为树)与极致的性能优化(如开放世界流

weixin_34355559的博客 329

虚幻引擎分辨率设置:SetScreenResolution与控制台命令的底层差异与实战避坑指南

在游戏开发与图形渲染中,分辨率控制是影响视觉表现与运行性能的核心参数之一。其原理涉及从应用层到渲染硬件接口(RHI)的完整管线协同,确保画面输出与系统状态同步。理解其技术价值在于,正确的分辨率管理能保障UI布局准确、后处理效果稳定,并避免画面撕裂等渲染异常。在虚幻引擎(UE4/UE5)的工程实践中,开发者常通过蓝图或C++调用`SetScreenResolution`,或使用`r.SetRes`控制台命令进行快速调试。然而,这两种方式在底层执行路径、状态同步及对动态分辨率系统的影响上存在根本性差异,错误选择

weixin_30875157的博客 331

UE5移动端渲染配置实战:Vulkan与ES3.1性能对比与选型指南

在移动端图形开发中,渲染API的选择是决定应用性能与兼容性的核心。从原理上看,图形API作为应用与GPU硬件沟通的桥梁,其设计直接影响了CPU开销、GPU资源调度效率与多线程并行能力。Vulkan作为新一代底层API,通过将命令缓冲、管线状态等控制权交还开发者,实现了极低的CPU开销与出色的多线程渲染支持,其技术价值在于能为中高端设备释放硬件潜能,尤其适用于CPU压力大、Draw Call密集的复杂3D场景。而OpenGL ES作为历经验证的高层API,凭借驱动层的深度优化与近乎全设备的覆盖,在追求最大兼容

weixin_33806300的博客 284

3D高斯泼溅技术实战:从原理到虚幻引擎5集成与优化

3D场景重建是计算机视觉与图形学领域的核心课题,旨在从2D图像或视频中恢复真实世界的三维结构。其基本原理是通过多视角几何、运动恢复结构(SfM)等技术,估算相机位姿并生成稀疏点云。随着神经渲染与可微渲染技术的发展,3D高斯泼溅(3D Gaussian Splatting)作为一种新兴的显式表示方法脱颖而出。它通过大量带有位置、协方差、不透明度及球谐函数系数的可学习高斯椭球体来表征场景,实现了高质量、高效率的视角相关渲染,其技术价值在于平衡了渲染质量与计算效率,为实时应用提供了新可能。该技术适用于数字孪生、V

weixin_30247781的博客 463

深入解析Unreal Engine RHI渲染硬件接口的设计原理与跨平台实践

渲染硬件接口(RHI)是现代游戏引擎实现跨平台渲染的核心抽象层,它定义了CPU与GPU之间的通信契约。其核心原理是通过一套统一的API接口,将高层的渲染指令翻译成不同图形API(如DirectX 12、Vulkan、Metal)能理解的底层命令,从而实现“一次编写,多平台运行”。这一设计不仅大幅降低了多平台适配的工程复杂度,更为性能优化和新技术集成提供了统一入口。在实时渲染领域,RHI的价值尤为凸显,它直接关系到渲染效率、资源管理以及前沿图形特性(如硬件光追加速、可变速率着色)的落地能力。无论是应对移动端与

weixin_33938733的博客 404
上一篇: 基于深度学习的渲染  Deep Learning Based Rendering
下一篇: UE高级性能剖析技术(2) -CPU帧率瓶颈和卡顿
leonwei
leonwei 领域专家: 游戏开发技术领域 领域专家: 游戏开发技术领域
博客等级 码龄19年 4371粉丝 125原创
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值