虚幻引擎渲染流程原理机制源码剖析

Viewed 44

说明

  • 需求:不论是增加自定义 MeshPass ,还是运行时去动态生成不存在的 Mesh ,还是相关资源的性能分析优化,都需要对 Mesh 从资产到 GPU 的完整的渲染流程原理机制有一定的了解。
  • 本文即是以Mesh为例,对虚幻引擎从资产到 GPU 的渲染流程原理机制源码进行剖析和总结。
  • 环境:本文基于 UE5.2,在 Windows 编辑器下和 Package 版本中进行测试和验证。
  • 注意:为了便于对执行流程进行调试,本文禁用了并行渲染和相关异步执行,让所有调用堆栈都能够显示在同一堆栈。原则上不影响基本原理和机制。相关指令:r.RHICmdBypass=1 、r.RDG.ImmediateMode=1,相关启动参数:-onethread (参见:渲染依赖图)。

关键类

全览

  • 本类图把 Mesh 的初始化和更新、绘制等涉及的类和函数都绘制出来了。可能较大,不便阅读,下文进行拆解说明。

FSceneRenderer

  • 根据当前平台和设置,使用不同的渲染管线 FSceneRenderer,如 PC 上默认使用延迟渲染管线 FDeferredShadingSceneRenderer ,移动平台使用 FMobileSceneRenderer (可为延迟可为前向,具体渲染管线的原理见:Unreal 渲染管线原理机制源码剖析),FSceneRenderer 对当前的场景视图 FScene 进行渲染。FScene 中保存有场景中所有需要渲染的物体的 FPrimitiveSceneInfo 。

FPrimitiveSceneProxy

  • FPrimitiveSceneProxy 是游戏线程的"UPrimitiveComponent"渲染线程表示。"FPrimitiveSceneProxy"负责通过对"GetDynamicMeshElements"和"DrawStaticElements"的回调将FMeshBatch提交给渲染器。不同类型的资源有不同的 FPrimitiveSceneProxy 子类。包含了特定类型渲染相关的信息,如几何体的顶点和索引数据、材质和纹理、光照和阴影信息等。


FPrimitiveSceneInfo

  • 这是单个 UPrimitiveComponent 的渲染器的内部状态。 它与引擎模块中的 FPrimitiveSceneProxy 具有一对一的映射。内部保存有网格绘制 FStaticMeshBatch 数组。



FStaticMeshBatch

  • FStaticMeshBatch 继承于 FMeshBatch ,是在场景片段构建时由基元定义且从未更改的网格。"FMeshBatch"将"FPrimitiveSceneProxy"实现(用户代码)与网格体通道(私有渲染器模块)解耦。它包含了通道确定最终着色器绑定和渲染状态所需的所有内容,如存储顶点相关数据的 FVertexFactory 以及材质渲染需要的 FMaterialRenderProxy 等。 FMeshBatch 也是网格绘制处理器 FMeshPassProcessor 及处理过程中的重要元素,存储在 FPrimitiveSceneInfo::StaticMeshes 中。


FMeshPassProcessor

  • 特定的通道网格体处理器派生自"FMeshPassProcessor"基类,负责将"FMeshBatch"转换为用于给定通道的网格体绘制命令(FMeshDrawCommand) 。这是最终的绘制筛选发生的地方,会选择适当的着色器并收集着色器绑定。根据通道作用,有多种子类实现。在需要实现自定义的 MeshPass 的时候,可以创建对应的 FMeshPassProcessor (见“基于 MeshPass 的模型外扩型 UE4 描边方案与实现总结”)。

  • FMeshPassProcessor 内部包含一个 FMeshPassDrawListContext ,FMeshPassProcessor 通过其并行调用 FRHICommandList 通知具体 RHI 去执行对应图形渲染操作。

FRenderResource

  • Render Thread 拥有的用于渲染的数据,如顶点数据、光照信息等。各类型的数据以 FRenderResource 的子类的形式存在,在 RHI thread 和 Game Thread 之间进行渲染数据的传递。

UStaticMesh

  • UStaticMesh 中存储有静态网格渲染数据 FStaticMeshRenderData ,FStaticMeshRenderData 包含 LOD 数据 FStaticMeshLODResources 以及顶点处理工程 FStaticMeshVertexFactories ,FStaticMeshLODResources 中包括顶点数据 FStaticMeshVertexBuffers 以及 LOD 部件 FStaticMeshSection ,FStaticMeshVertexBuffers 中包含顶点数据 FStaticMeshVertexBuffer、顶点位置数据 PositionVertexBuffer 及顶点颜色数据 ColorVertexBuffer ,这三个都是 FRenderResource 。FStaticMeshVertexFactories 包含用于这个网格的渲染的 FLocalVertexFactory ,其继承于 FVertexFactory ,也是一种 FRenderResource。

FMeshDrawCommand

  • FMeshDrawCommand 是 FMeshBatch 和 RHI 之间的接口。它是一个完全无状态的绘制描述,存储了RHI需要知道的关于网格体绘制的所有信息:要使用的着色器、其资源绑定、绘制调用参数。这允许在RHI级别之上缓存和合并绘制调用。

IRHICommandContext

  • IRHICommandContext 是 RHI 命令上下文的接口类,定义了一些图形 API 相关的操作。在可以并行处理命令列表的平台上,它是一个单独的对象,有自己的实现类(如 FMetalRHICommandContext 、FD3D12CommandContextBase 及 FVulkanCommandListContext 等)。 FRHICommandList 会调用对应的 IRHICommandContext 去执行对应的具体的渲染图形 API 。

FDynamicRHI

  • 动态绑定RHI实现的接口

FStaticMeshLODResources

  • FStaticMeshLODResources 中存储有 FStaticMeshVertexBuffers 类型的 VertexBuffers ,FRawStaticIndexBuffer 类型的 IndexBuffer




关键流程

资源的准备和初始化

顶点等渲染数据的获取和准备

[RenderTestUE5-Win64-Debug.exe] FStaticMeshLODResources::SerializeBuffers(FArchive &,UStaticMesh *,unsigned char,FStaticMeshLODResources::FStaticMeshBuffersSize &) StaticMesh.cpp:472
[RenderTestUE5-Win64-Debug.exe] FStaticMeshLODResources::Serialize(FArchive &,UObject *,int) StaticMesh.cpp:761
[RenderTestUE5-Win64-Debug.exe] TIndirectArray<FStaticMeshLODResources,TSizedDefaultAllocator<32> >::Serialize(FArchive &,UObject *) IndirectArray.h:220
[RenderTestUE5-Win64-Debug.exe] FStaticMeshRenderData::Serialize(FArchive &,UStaticMesh *,bool) StaticMesh.cpp:1724
[RenderTestUE5-Win64-Debug.exe] UStaticMesh::Serialize(FArchive &) StaticMesh.cpp:5593
[RenderTestUE5-Win64-Debug.exe] FAsyncPackage2::EventDrivenSerializeExport(const FAsyncPackageHeaderData &,const TArrayView<FExportObject,int> &,int,FExportArchive &) AsyncLoading2.cpp:6007
[RenderTestUE5-Win64-Debug.exe] FAsyncPackage2::Event_ProcessExportBundle(FAsyncLoadingThreadState2 &,FAsyncPackage2 *,int) AsyncLoading2.cpp:5639
[RenderTestUE5-Win64-Debug.exe] FEventLoadNode2::Execute(FAsyncLoadingThreadState2 &) AsyncLoading2.cpp:3983
[RenderTestUE5-Win64-Debug.exe] FAsyncLoadEventQueue2::ExecuteSyncLoadEvents(FAsyncLoadingThreadState2 &) AsyncLoading2.cpp:4171
[RenderTestUE5-Win64-Debug.exe] FAsyncLoadingThread2::ProcessAsyncLoadingFromGameThread(FAsyncLoadingThreadState2 &,bool &) AsyncLoading2.cpp:6655
[RenderTestUE5-Win64-Debug.exe] FAsyncLoadingThread2::TickAsyncThreadFromGameThread(FAsyncLoadingThreadState2 &,bool &) AsyncLoading2.cpp:7325
[RenderTestUE5-Win64-Debug.exe] FAsyncLoadingThread2::TickAsyncLoadingFromGameThread(FAsyncLoadingThreadState2 &,bool,bool,double,int,bool &) AsyncLoading2.cpp:7009
[RenderTestUE5-Win64-Debug.exe] FAsyncLoadingThread2::FlushLoading(int) AsyncLoading2.cpp:8217
[RenderTestUE5-Win64-Debug.exe] FlushAsyncLoading(int) AsyncPackageLoader.cpp:280
[RenderTestUE5-Win64-Debug.exe] LoadPackageInternal(UPackage *,const FPackagePath &,unsigned int,FLinkerLoad *,FArchive *,const FLinkerInstancingContext *,const FPackagePath *) UObjectGlobals.cpp:1581
[RenderTestUE5-Win64-Debug.exe] LoadPackage(UPackage *,const FPackagePath &,unsigned int,FArchive *,const FLinkerInstancingContext *,const FPackagePath *) UObjectGlobals.cpp:1958
[RenderTestUE5-Win64-Debug.exe] LoadPackage(UPackage *,const wchar_t *,unsigned int,FArchive *,const FLinkerInstancingContext *) UObjectGlobals.cpp:1931
[RenderTestUE5-Win64-Debug.exe] UEngine::LoadMap(FWorldContext &,FURL,UPendingNetGame *,FString &) UnrealEngine.cpp:14706
[RenderTestUE5-Win64-Debug.exe] UEngine::Browse(FWorldContext &,FURL,FString &) UnrealEngine.cpp:14108
[RenderTestUE5-Win64-Debug.exe] UGameInstance::StartGameInstance() GameInstance.cpp:641
[RenderTestUE5-Win64-Debug.exe] UGameEngine::Start() GameEngine.cpp:1212
[RenderTestUE5-Win64-Debug.exe] FEngineLoop::Init() LaunchEngineLoop.cpp:4820
[RenderTestUE5-Win64-Debug.exe] EngineInit() Launch.cpp:51
[RenderTestUE5-Win64-Debug.exe] GuardedMain(const wchar_t *) Launch.cpp:166
[RenderTestUE5-Win64-Debug.exe] LaunchWindowsStartup(HINSTANCE__ *,HINSTANCE__ *,char *,int,const wchar_t *) LaunchWindows.cpp:233
[RenderTestUE5-Win64-Debug.exe] WinMain(HINSTANCE__ *,HINSTANCE__ *,char *,int) LaunchWindows.cpp:284
[Inlined] [RenderTestUE5-Win64-Debug.exe] invoke_main() 0x00007ff651c85b96
[RenderTestUE5-Win64-Debug.exe] __scrt_common_main_seh() 0x00007ff651c85b75
[kernel32.dll] <unknown> 0x00007ffefbb37604
[ntdll.dll] <unknown> 0x00007ffefdb026a1

  • 也可能直接通过代码(含蓝图)来指定顶点、三角形等渲染所需的数据(如 UProceduralMeshComponent 、UCustomMeshComponent 等)。






RHI 资源的初始化

  • 资源加载完毕反序列化完成后执行的 PostLoad 中(如 StaticMesh)触发。
[RenderTestUE5-Win64-Debug.exe] BeginInitResource(FRenderResource *) RenderResource.cpp:372
[RenderTestUE5-Win64-Debug.exe] FStaticMeshLODResources::InitResources(UStaticMesh *,int) StaticMesh.cpp:1320
[RenderTestUE5-Win64-Debug.exe] FStaticMeshRenderData::InitResources(Type,UStaticMesh *) StaticMesh.cpp:1880
[RenderTestUE5-Win64-Debug.exe] UStaticMesh::InitResources() StaticMesh.cpp:3469
[RenderTestUE5-Win64-Debug.exe] UStaticMesh::FinishPostLoadInternal(FStaticMeshPostLoadContext &) StaticMesh.cpp:6493
[RenderTestUE5-Win64-Debug.exe] UStaticMesh::PostLoad() StaticMesh.cpp:5832
[RenderTestUE5-Win64-Debug.exe] UObject::ConditionalPostLoad() Obj.cpp:1121
[RenderTestUE5-Win64-Debug.exe] UBodySetup::PostLoad() BodySetup.cpp:1005
[RenderTestUE5-Win64-Debug.exe] UObject::ConditionalPostLoad() Obj.cpp:1121
//...
[UnrealEditor-RenderCore-Win64-Debug.dll] BeginInitResource(FRenderResource *) RenderResource.cpp:373
[UnrealEditor-ProceduralMeshComponent-Win64-Debug.dll] FProceduralMeshSceneProxy::FProceduralMeshSceneProxy(UProceduralMeshComponent *) ProceduralMeshComponent.cpp:157
[UnrealEditor-ProceduralMeshComponent-Win64-Debug.dll] UProceduralMeshComponent::CreateSceneProxy() ProceduralMeshComponent.cpp:904
[UnrealEditor-Renderer-Win64-Debug.dll] FScene::AddPrimitive(UPrimitiveComponent *) RendererScene.cpp:2028
[UnrealEditor-Engine-Win64-Debug.dll] UPrimitiveComponent::CreateRenderState_Concurrent(FRegisterComponentContext *) PrimitiveComponent.cpp:588
//...
  • 对于编辑器下 fbx 等资产的导入,也会在导入完毕( Build 结束)后触发 。
[UnrealEditor-Engine-Win64-Debug.dll] UStaticMesh::InitResources() StaticMesh.cpp:3439
[UnrealEditor-Engine-Win64-Debug.dll] UStaticMesh::FinishBuildInternal(const TArray<UStaticMeshComponent *,TSizedDefaultAllocator<32> > &,bool,bool) StaticMeshBuild.cpp:600
[UnrealEditor-Engine-Win64-Debug.dll] UStaticMesh::BatchBuild(const TArray<UStaticMesh *,TSizedDefaultAllocator<32> > &,const UStaticMesh::FBuildParameters &,TFunction<bool __cdecl(UStaticMesh *)>) StaticMeshBuild.cpp:339
[UnrealEditor-Engine-Win64-Debug.dll] UStaticMesh::Build(const UStaticMesh::FBuildParameters &) StaticMeshBuild.cpp:124
[UnrealEditor-Engine-Win64-Debug.dll] UStaticMesh::Build(bool,TArray<FText,TSizedDefaultAllocator<32> > *) StaticMeshBuild.cpp:360
[UnrealEditor-UnrealEd-Win64-Debug.dll] UnFbx::FFbxImporter::PostImportStaticMesh(UStaticMesh *,TArray<fbxsdk::FbxNode *,TSizedDefaultAllocator<32> > &,int) FbxStaticMeshImport.cpp:2317
[UnrealEditor-UnrealEd-Win64-Debug.dll] UFbxFactory::RecursiveImportNode(UnFbx::FFbxImporter *,void *,UObject *,FName,EObjectFlags,FScopedSlowTask &,TArray<UObject *,TSizedDefaultAllocator<32> > &) FbxFactory.cpp:1082
[UnrealEditor-UnrealEd-Win64-Debug.dll] UFbxFactory::RecursiveImportNode(UnFbx::FFbxImporter *,void *,UObject *,FName,EObjectFlags,FScopedSlowTask &,TArray<UObject *,TSizedDefaultAllocator<32> > &) FbxFactory.cpp:1096
[UnrealEditor-UnrealEd-Win64-Debug.dll] UFbxFactory::FactoryCreateFile(UClass *,UObject *,FName,EObjectFlags,const FString &,const wchar_t *,FFeedbackContext *,bool &) FbxFactory.cpp:601
[UnrealEditor-UnrealEd-Win64-Debug.dll] UFactory::ImportObject(UClass *,UObject *,FName,EObjectFlags,const FString &,const wchar_t *,bool &) Factory.cpp:208
//...
  • Game Thread 通过 BeginInitResource 把 FRenderResource 数据传给 Render Thread ,Render Thread 调用 FRenderResource 的 InitResource 来把资源跟 RHI 进行绑定 。



  • 游戏线程的 BeginInitResource 通过 ENQUEUE_RENDER_COMMAND 给渲染线程派发 InitCommand 命令来执行资源的初始化。

  • 各 FRenderResource 重载并调用对应的 InitRHI 去通知 RHI 执行资源初始化。


Proxy 代理的初始化

  • 在帧末 UWorld::SendAllEndOfFrameUpdates 或 UActorComponent 执行 ExecuteRegisterEvents 时,通过 CreateRenderState_Concurrent 调用 FScene 的 AddPrimitive 来触发。
  • 调用对应 UPrimitiveComponent 的 CreateSceneProxy 创建对应的资源代理 FPrimitiveSceneProxy ,根据各 UPrimitiveComponent (如 UStaticMeshComponent 、UProceduralMeshComponent 等)生成对应的 FPrimitiveSceneInfo 。
[UnrealEditor-Engine-Win64-Debug.dll] UStaticMeshComponent::CreateSceneProxy() StaticMeshRender.cpp:2539
[UnrealEditor-Renderer-Win64-Debug.dll] FScene::AddPrimitive(UPrimitiveComponent *) RendererScene.cpp:2028
[UnrealEditor-Engine-Win64-Debug.dll] UPrimitiveComponent::CreateRenderState_Concurrent(FRegisterComponentContext *) PrimitiveComponent.cpp:588
[UnrealEditor-Engine-Win64-Debug.dll] UStaticMeshComponent::CreateRenderState_Concurrent(FRegisterComponentContext *) StaticMeshComponent.cpp:791
//...


[UnrealEditor-Renderer-Win64-Debug.dll] FPrimitiveSceneInfo::FPrimitiveSceneInfo(UPrimitiveComponent *,FScene *) PrimitiveSceneInfo.cpp:247
[UnrealEditor-Renderer-Win64-Debug.dll] FScene::AddPrimitive(UPrimitiveComponent *) RendererScene.cpp:2037
[UnrealEditor-Engine-Win64-Debug.dll] UPrimitiveComponent::CreateRenderState_Concurrent(FRegisterComponentContext *) PrimitiveComponent.cpp:588
[UnrealEditor-Engine-Win64-Debug.dll] UStaticMeshComponent::CreateRenderState_Concurrent(FRegisterComponentContext *) StaticMeshComponent.cpp:791
//...


  • 可以在各自的 CreateSceneProxy 里做一些特定逻辑,如判断检测(FStaticMeshSceneProxy)

  • 之后调用各 FPrimitiveSceneProxy 的构造函数,对资源做引用和初始化(如从 UStaticMesh 获取到存储重要渲染数据的 FStaticMeshRenderData 类型的 RenderData 存到 FStaticMeshSceneProxy )。

  • 也可在 FPrimitiveSceneProxy 的构造函数中初始化渲染数据(如 FProceduralMeshSceneProxy 对 BeginInitResource 的调用)。

Mesh 的创建和绘制

获取或创建 FMeshBatch

  • "FPrimitiveSceneProxy"负责通过对"GetDynamicMeshElements"和"DrawStaticElements"的回调将 FMeshBatch 提交给渲染器。
  • "FPrimitiveSceneProxy"有两个生成"FMeshBatches"的路径:缓存路径和动态路径。"FPrimitiveSceneProxy"实现通过"GetViewRelevance()"函数控制每个帧使用的路径。


  • 动态路径每一帧重新创建"FMeshBatch"。这是最灵活的路径,用于在帧与帧之间经常会发生变化的绘制,例如粒子。它由"GetDynamicMeshElements"实现。该函数从InitViews中调用每一帧,并为每个视图创建一个临时的"FMeshBatch"。又如 FProceduralMeshSceneProxy 。
[UnrealEditor-Engine-Win64-Debug.dll] FMeshElementCollector::AllocateMesh() SceneManagement.h:1901
[UnrealEditor-ProceduralMeshComponent-Win64-Debug.dll] FProceduralMeshSceneProxy::GetDynamicMeshElements(const TArray<FSceneView const *,TSizedDefaultAllocator<32> > &,const FSceneViewFamily &,unsigned int,FMeshElementCollector &) ProceduralMeshComponent.cpp:374
[UnrealEditor-Renderer-Win64-Debug.dll] FSceneRenderer::GatherDynamicMeshElements(TArray<FViewInfo,TSizedDefaultAllocator<32> > &,const FScene *,const FSceneViewFamily &,FGlobalDynamicIndexBuffer &,FGlobalDynamicVertexBuffer &,FGlobalDynamicReadBuffer &,const TArray<unsigned char,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > &,const TArray<unsigned char,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > &,FMeshElementCollector &) SceneVisibility.cpp:3537
[UnrealEditor-Renderer-Win64-Debug.dll] FSceneRenderer::ComputeViewVisibility(FRHICommandListImmediate &,Type,TArray<FViewCommands,TSizedInlineAllocator<4,32,TSizedDefaultAllocator<32> > > &,FGlobalDynamicIndexBuffer &,FGlobalDynamicVertexBuffer &,FGlobalDynamicReadBuffer &,FInstanceCullingManager &) SceneVisibility.cpp:4963
[UnrealEditor-Renderer-Win64-Debug.dll] FDeferredShadingSceneRenderer::BeginInitViews(FRDGBuilder &,const FSceneTexturesConfig &,Type,FILCUpdatePrimTaskData &,FInstanceCullingManager &) SceneVisibility.cpp:5293
[UnrealEditor-Renderer-Win64-Debug.dll] FDeferredShadingSceneRenderer::Render(FRDGBuilder &) DeferredShadingRenderer.cpp:2638
//...

  • 缓存的路径构建并重用"FMeshBatch",对于不改变每一帧(比如静态网格体)的绘制,它是快速渲染的首选路径。这是由"DrawStaticElements"实现的,当一个代理被添加到场景中(AddToScene)时会调用此函数,以更新场景图元的可见性(UpdateAllPrimitiveSceneInfos)。创建的"FMeshBatches"存储在"FPrimitiveSceneInfo::StaticMeshes"中,并且每一帧都被重用,直到从场景中删除代理为止。

//...
[UnrealEditor-Engine-Win64-Debug.dll] FStaticMeshSceneProxy::DrawStaticElements(FStaticPrimitiveDrawInterface *) StaticMeshRender.cpp:1337
[UnrealEditor-Renderer-Win64-Debug.dll] <lambda_41e261a582484762413a1fb8ca15cb31>::operator()(int) PrimitiveSceneInfo.cpp:1130
[UnrealEditor-Renderer-Win64-Debug.dll] ParallelForImpl::ParallelForInternal<<lambda_41e261a582484762413a1fb8ca15cb31>,<lambda_7c84b8ec2f516ba7c0c460f9f2c9eb99>,std::nullptr_t>(const wchar_t *,int,int,<lambda_41e261a582484762413a1fb8ca15cb31>,<lambda_7c84b8ec2f516ba7c0c460f9f2c9eb99>,EParallelForFlags,const TArrayView<std::nullptr_t,int> &) ParallelFor.h:137
[UnrealEditor-Renderer-Win64-Debug.dll] ParallelForTemplate<<lambda_41e261a582484762413a1fb8ca15cb31> >(int,const <lambda_41e261a582484762413a1fb8ca15cb31> &,EParallelForFlags) ParallelFor.h:462
[UnrealEditor-Renderer-Win64-Debug.dll] FPrimitiveSceneInfo::AddStaticMeshes(FScene *,TArrayView<FPrimitiveSceneInfo *,int>,bool) PrimitiveSceneInfo.cpp:1122
[UnrealEditor-Renderer-Win64-Debug.dll] FPrimitiveSceneInfo::AddToScene(FScene *,TArrayView<FPrimitiveSceneInfo *,int>,EPrimitiveAddToSceneOps) PrimitiveSceneInfo.cpp:1462
[UnrealEditor-Renderer-Win64-Debug.dll] FScene::UpdateAllPrimitiveSceneInfos(FRDGBuilder &,EUpdateAllPrimitiveSceneInfosAsyncOps) RendererScene.cpp:6100
[UnrealEditor-Renderer-Win64-Debug.dll] FDeferredShadingSceneRenderer::Render(FRDGBuilder &) DeferredShadingRenderer.cpp:2445
//...
  • 缓存的网格体绘制命令是"FPrimitiveSceneInfo::CacheMeshDrawCommands"中内置的"FPrimitiveSceneInfo::AddToScene"。使用这些命令绘制非常有效,因为我们只需每帧选择适当的预构建命令即可("FDrawCommandRelevancePacket::AddCommandsForMesh")。只有在绘制状态不每帧都改变,且可以在AddToScene内设置所有着色器绑定时,才能缓存的绘制命令(详见:网格体绘制管道 - 缓存的网格体绘制命令)。

创建 FMeshDrawCommand

  • FMeshDrawCommand 由特定于网格体通道的 FMeshPassProcessor 根据 FMeshBatch 创建,创建时间可为渲染管线的绘制早期, BeginInitViews 的 ComputeViewVisibility 中,计算图元可见性时。
[UnrealEditor-Renderer-Win64-Debug.dll] FMeshPassProcessor::BuildMeshDrawCommands<TMeshProcessorShaders<TBasePassVertexShaderPolicyParamType<FUniformLightMapPolicy>,TBasePassPixelShaderPolicyParamType<FUniformLightMapPolicy>,FMeshMaterialShader,FMeshMaterialShader,FMeshMaterialShader>,TBasePassShaderElementData<FUniformLightMapPolicy> >(const FMeshBatch &__restrict,unsigned long long,const FPrimitiveSceneProxy *__restrict,const FMaterialRenderProxy &__restrict,const FMaterial &__restrict,const FMeshPassProcessorRenderState &__restrict,TMeshProcessorShaders<TBasePassVertexShaderPolicyParamType<FUniformLightMapPolicy>,TBasePassPixelShaderPolicyParamType<FUniformLightMapPolicy>,FMeshMaterialShader,FMeshMaterialShader,FMeshMaterialShader>,ERasterizerFillMode,ERasterizerCullMode,FMeshDrawCommandSortKey,EMeshPassFeatures,const TBasePassShaderElementData<FUniformLightMapPolicy> &) MeshPassProcessor.inl:60
[UnrealEditor-Renderer-Win64-Debug.dll] FBasePassMeshProcessor::Process<FUniformLightMapPolicy>(const FMeshBatch &__restrict,unsigned long long,int,const FPrimitiveSceneProxy *__restrict,const FMaterialRenderProxy &__restrict,const FMaterial &__restrict,const bool,const bool,FMaterialShadingModelField,const FUniformLightMapPolicy &__restrict,const FLightCacheInterface *const &__restrict,ERasterizerFillMode,ERasterizerCullMode) BasePassRendering.cpp:1817
[UnrealEditor-Renderer-Win64-Debug.dll] FBasePassMeshProcessor::TryAddMeshBatch(const FMeshBatch &__restrict,unsigned long long,const FPrimitiveSceneProxy *__restrict,int,const FMaterialRenderProxy &,const FMaterial &) BasePassRendering.cpp:2077
[UnrealEditor-Renderer-Win64-Debug.dll] FBasePassMeshProcessor::AddMeshBatch(const FMeshBatch &__restrict,unsigned long long,const FPrimitiveSceneProxy *__restrict,int) BasePassRendering.cpp:1845
[UnrealEditor-Renderer-Win64-Debug.dll] GenerateDynamicMeshDrawCommands(const FViewInfo &,EShadingPath,Type,FMeshPassProcessor *,const TArray<FMeshBatchAndRelevance,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > &,const TArray<FMeshPassMask,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > *,int,const TArray<FStaticMeshBatch const *,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > &,int,TArray<FVisibleMeshDrawCommand,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > &,FDynamicMeshDrawCommandStorage &,Experimental::TRobinHoodHashSet<FGraphicsMinimalPipelineStateInitializer,DefaultKeyFuncs<FGraphicsMinimalPipelineStateInitializer,0>,TSizedDefaultAllocator<32> > &,bool &) MeshDrawCommands.cpp:611
[UnrealEditor-Renderer-Win64-Debug.dll] FMeshDrawCommandPassSetupTask::AnyThreadTask() MeshDrawCommands.cpp:901
[UnrealEditor-Renderer-Win64-Debug.dll] FParallelMeshDrawCommandPass::DispatchPassSetup(FScene *,const FViewInfo &,FInstanceCullingContext &&,Type,Type,FMeshPassProcessor *,const TArray<FMeshBatchAndRelevance,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > &,const TArray<FMeshPassMask,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > *,int,TArray<FStaticMeshBatch const *,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > &,int,TArray<FVisibleMeshDrawCommand,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > &,FMeshPassProcessor *,TArray<FVisibleMeshDrawCommand,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > *) MeshDrawCommands.cpp:1278
[UnrealEditor-Renderer-Win64-Debug.dll] FSceneRenderer::SetupMeshPass(FViewInfo &,Type,FViewCommands &,FInstanceCullingManager &) SceneRendering.cpp:3826
[UnrealEditor-Renderer-Win64-Debug.dll] FSceneRenderer::ComputeViewVisibility(FRHICommandListImmediate &,Type,TArray<FViewCommands,TSizedInlineAllocator<4,32,TSizedDefaultAllocator<32> > > &,FGlobalDynamicIndexBuffer &,FGlobalDynamicVertexBuffer &,FGlobalDynamicReadBuffer &,FInstanceCullingManager &) SceneVisibility.cpp:4988
[UnrealEditor-Renderer-Win64-Debug.dll] FDeferredShadingSceneRenderer::BeginInitViews(FRDGBuilder &,const FSceneTexturesConfig &,Type,FILCUpdatePrimTaskData &,FInstanceCullingManager &) SceneVisibility.cpp:5293
[UnrealEditor-Renderer-Win64-Debug.dll] FDeferredShadingSceneRenderer::Render(FRDGBuilder &) DeferredShadingRenderer.cpp:2638
//...

[UnrealEditor-Renderer-Win64-Debug.dll] FMeshPassProcessor::BuildMeshDrawCommands<TMeshProcessorShaders<TDepthOnlyVS<1>,FDepthOnlyPS,FMeshMaterialShader,FMeshMaterialShader,FMeshMaterialShader>,FMeshMaterialShaderElementData>(const FMeshBatch &__restrict,unsigned long long,const FPrimitiveSceneProxy *__restrict,const FMaterialRenderProxy &__restrict,const FMaterial &__restrict,const FMeshPassProcessorRenderState &__restrict,TMeshProcessorShaders<TDepthOnlyVS<1>,FDepthOnlyPS,FMeshMaterialShader,FMeshMaterialShader,FMeshMaterialShader>,ERasterizerFillMode,ERasterizerCullMode,FMeshDrawCommandSortKey,EMeshPassFeatures,const FMeshMaterialShaderElementData &) MeshPassProcessor.inl:60
[UnrealEditor-Renderer-Win64-Debug.dll] FDepthPassMeshProcessor::Process<1>(const FMeshBatch &__restrict,unsigned long long,int,const FPrimitiveSceneProxy *__restrict,const FMaterialRenderProxy &__restrict,const FMaterial &__restrict,ERasterizerFillMode,ERasterizerCullMode) DepthRendering.cpp:788
[UnrealEditor-Renderer-Win64-Debug.dll] FDepthPassMeshProcessor::TryAddMeshBatch(const FMeshBatch &__restrict,unsigned long long,const FPrimitiveSceneProxy *__restrict,int,const FMaterialRenderProxy &,const FMaterial &) DepthRendering.cpp:923
[UnrealEditor-Renderer-Win64-Debug.dll] FDepthPassMeshProcessor::AddMeshBatch(const FMeshBatch &__restrict,unsigned long long,const FPrimitiveSceneProxy *__restrict,int) DepthRendering.cpp:1004
[UnrealEditor-Renderer-Win64-Debug.dll] GenerateDynamicMeshDrawCommands(const FViewInfo &,EShadingPath,Type,FMeshPassProcessor *,const TArray<FMeshBatchAndRelevance,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > &,const TArray<FMeshPassMask,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > *,int,const TArray<FStaticMeshBatch const *,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > &,int,TArray<FVisibleMeshDrawCommand,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > &,FDynamicMeshDrawCommandStorage &,Experimental::TRobinHoodHashSet<FGraphicsMinimalPipelineStateInitializer,DefaultKeyFuncs<FGraphicsMinimalPipelineStateInitializer,0>,TSizedDefaultAllocator<32> > &,bool &) MeshDrawCommands.cpp:611
//...

[UnrealEditor-Renderer-Win64-Debug.dll] FMeshPassProcessor::BuildMeshDrawCommands<TMeshProcessorShaders<FHitProxyVS,FHitProxyPS,FMeshMaterialShader,FMeshMaterialShader,FMeshMaterialShader>,FHitProxyShaderElementData>(const FMeshBatch &__restrict,unsigned long long,const FPrimitiveSceneProxy *__restrict,const FMaterialRenderProxy &__restrict,const FMaterial &__restrict,const FMeshPassProcessorRenderState &__restrict,TMeshProcessorShaders<FHitProxyVS,FHitProxyPS,FMeshMaterialShader,FMeshMaterialShader,FMeshMaterialShader>,ERasterizerFillMode,ERasterizerCullMode,FMeshDrawCommandSortKey,EMeshPassFeatures,const FHitProxyShaderElementData &) MeshPassProcessor.inl:60
[UnrealEditor-Renderer-Win64-Debug.dll] FHitProxyMeshProcessor::Process(const FMeshBatch &,unsigned long long,int,const FPrimitiveSceneProxy *__restrict,const FMaterialRenderProxy &__restrict,const FMaterial &__restrict,ERasterizerFillMode,ERasterizerCullMode) SceneHitProxyRendering.cpp:887
[UnrealEditor-Renderer-Win64-Debug.dll] FHitProxyMeshProcessor::TryAddMeshBatch(const FMeshBatch &__restrict,unsigned long long,const FPrimitiveSceneProxy *__restrict,int,const FMaterialRenderProxy *,const FMaterial *) SceneHitProxyRendering.cpp:802
[UnrealEditor-Renderer-Win64-Debug.dll] FHitProxyMeshProcessor::AddMeshBatch(const FMeshBatch &__restrict,unsigned long long,const FPrimitiveSceneProxy *__restrict,int) SceneHitProxyRendering.cpp:822
[UnrealEditor-Renderer-Win64-Debug.dll] GenerateDynamicMeshDrawCommands(const FViewInfo &,EShadingPath,Type,FMeshPassProcessor *,const TArray<FMeshBatchAndRelevance,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > &,const TArray<FMeshPassMask,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > *,int,const TArray<FStaticMeshBatch const *,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > &,int,TArray<FVisibleMeshDrawCommand,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > &,FDynamicMeshDrawCommandStorage &,Experimental::TRobinHoodHashSet<FGraphicsMinimalPipelineStateInitializer,DefaultKeyFuncs<FGraphicsMinimalPipelineStateInitializer,0>,TSizedDefaultAllocator<32> > &,bool &) MeshDrawCommands.cpp:611
//...

把各种渲染指令(RHICommandList)提交给 RHI 进行渲染

  • "SubmitMeshDrawCommands"用于将"FMeshDrawCommand"转换为RHICommandList上设置的一系列RHI命令。
[UnrealEditor-D3D12RHI-Win64-Debug.dll] FD3D12CommandContext::RHIDrawIndexedPrimitive(FRHIBuffer *,int,unsigned int,unsigned int,unsigned int,unsigned int,unsigned int) D3D12Commands.cpp:1683
[UnrealEditor-RHI-Win64-Debug.dll] FRHICommandList::DrawIndexedPrimitive(FRHIBuffer *,int,unsigned int,unsigned int,unsigned int,unsigned int,unsigned int) RHICommandList.h:3570
[UnrealEditor-Renderer-Win64-Debug.dll] FMeshDrawCommand::SubmitDrawEnd(const FMeshDrawCommand &,unsigned int,FRHICommandList &,FRHIBuffer *,unsigned int) MeshPassProcessor.cpp:1425
[UnrealEditor-Renderer-Win64-Debug.dll] FMeshDrawCommand::SubmitDraw(const FMeshDrawCommand &__restrict,const Experimental::TRobinHoodHashSet<FGraphicsMinimalPipelineStateInitializer,DefaultKeyFuncs<FGraphicsMinimalPipelineStateInitializer,0>,TSizedDefaultAllocator<32> > &,FRHIBuffer *,int,unsigned int,FRHICommandList &,FMeshDrawCommandStateCache &__restrict,FRHIBuffer *,unsigned int) MeshPassProcessor.cpp:1579
[UnrealEditor-Renderer-Win64-Debug.dll] FInstanceCullingContext::SubmitDrawCommands(const TArray<FVisibleMeshDrawCommand,TConcurrentLinearArrayAllocator<FSceneRenderingBlockAllocationTag> > &,const Experimental::TRobinHoodHashSet<FGraphicsMinimalPipelineStateInitializer,DefaultKeyFuncs<FGraphicsMinimalPipelineStateInitializer,0>,TSizedDefaultAllocator<32> > &,const FMeshDrawCommandOverrideArgs &,int,int,unsigned int,FRHICommandList &) InstanceCullingContext.cpp:1385
[UnrealEditor-Renderer-Win64-Debug.dll] FParallelMeshDrawCommandPass::DispatchDraw(FParallelCommandListSet *,FRHICommandList &,const FInstanceCullingDrawParams *) MeshDrawCommands.cpp:1518
[UnrealEditor-Renderer-Win64-Debug.dll] <lambda_797059e689aeb755e3ff96eef5d65521>::operator()(FRHICommandList &) BasePassRendering.cpp:1552
[UnrealEditor-Renderer-Win64-Debug.dll] TRDGLambdaPass<FOpaqueBasePassParameters,<lambda_797059e689aeb755e3ff96eef5d65521> >::Execute(FRHIComputeCommandList &) RenderGraphPass.h:614
[UnrealEditor-RenderCore-Win64-Debug.dll] FRDGBuilder::ExecutePass(FRDGPass *,FRHIComputeCommandList &) RenderGraphBuilder.cpp:2904
[UnrealEditor-RenderCore-Win64-Debug.dll] FRDGBuilder::SetupAuxiliaryPasses(FRDGPass *) RenderGraphBuilder.cpp:2403
[UnrealEditor-RenderCore-Win64-Debug.dll] FRDGBuilder::SetupParameterPass(FRDGPass *) RenderGraphBuilder.cpp:2430
[UnrealEditor-Renderer-Win64-Debug.dll] FRDGBuilder::AddPassInternal<FOpaqueBasePassParameters,<lambda_797059e689aeb755e3ff96eef5d65521> >(FRDGEventName &&,const FShaderParametersMetadata *,const FOpaqueBasePassParameters *,ERDGPassFlags,<lambda_797059e689aeb755e3ff96eef5d65521> &&) RenderGraphBuilder.inl:268
[UnrealEditor-Renderer-Win64-Debug.dll] FRDGBuilder::AddPass<FOpaqueBasePassParameters,<lambda_797059e689aeb755e3ff96eef5d65521> >(FRDGEventName &&,const FOpaqueBasePassParameters *,ERDGPassFlags,<lambda_797059e689aeb755e3ff96eef5d65521> &&) RenderGraphBuilder.inl:290
[UnrealEditor-Renderer-Win64-Debug.dll] FDeferredShadingSceneRenderer::RenderBasePassInternal(FRDGBuilder &,const FSceneTextures &,const FRenderTargetBindingSlots &,Type,const FForwardBasePassTextures &,const FDBufferTextures &,bool,bool,FInstanceCullingManager &,bool,const TArrayView<Nanite::FRasterResults,int> &) BasePassRendering.cpp:1545
[UnrealEditor-Renderer-Win64-Debug.dll] FDeferredShadingSceneRenderer::RenderBasePass(FRDGBuilder &,FSceneTextures &,const FDBufferTextures &,Type,FRDGTexture *,FInstanceCullingManager &,bool,const TArrayView<Nanite::FRasterResults,int> &) BasePassRendering.cpp:1138
[UnrealEditor-Renderer-Win64-Debug.dll] FDeferredShadingSceneRenderer::Render(FRDGBuilder &) DeferredShadingRenderer.cpp:3431
[UnrealEditor-Renderer-Win64-Debug.dll] RenderViewFamilies_RenderThread(FRHICommandListImmediate &,const TArray<FSceneRenderer *,TSizedDefaultAllocator<32> > &) SceneRendering.cpp:4410
[UnrealEditor-Renderer-Win64-Debug.dll] <lambda_e3e20e1995854aad47e7738a41c7b507>::operator()(FRHICommandListImmediate &) SceneRendering.cpp:4679
[UnrealEditor-Renderer-Win64-Debug.dll] EnqueueUniqueRenderCommand<`FRendererModule::BeginRenderingViewFamilies'::`87'::FDrawSceneCommandName,<lambda_e3e20e1995854aad47e7738a41c7b507> >(<lambda_e3e20e1995854aad47e7738a41c7b507> &&) RenderingThread.h:270
[UnrealEditor-Renderer-Win64-Debug.dll] FRendererModule::BeginRenderingViewFamilies(FCanvas *,TArrayView<FSceneViewFamily *,int>) SceneRendering.cpp:4673
[UnrealEditor-Renderer-Win64-Debug.dll] FRendererModule::BeginRenderingViewFamily(FCanvas *,FSceneViewFamily *) SceneRendering.cpp:4529
[UnrealEditor-Engine-Win64-Debug.dll] UGameViewportClient::Draw(FViewport *,FCanvas *) GameViewportClient.cpp:1705
[UnrealEditor-Engine-Win64-Debug.dll] FViewport::Draw(bool) UnrealClient.cpp:1850
[UnrealEditor-UnrealEd-Win64-Debug.dll] UEditorEngine::Tick(float,bool) EditorEngine.cpp:2159
[UnrealEditor-UnrealEd-Win64-Debug.dll] UUnrealEdEngine::Tick(float,bool) UnrealEdEngine.cpp:516
[UnrealEditor-Win64-Debug.exe] FEngineLoop::Tick() LaunchEngineLoop.cpp:5806
[UnrealEditor-Win64-Debug.exe] EngineTick() Launch.cpp:61
[UnrealEditor-Win64-Debug.exe] GuardedMain(const wchar_t *) Launch.cpp:190
[UnrealEditor-Win64-Debug.exe] LaunchWindowsStartup(HINSTANCE__ *,HINSTANCE__ *,char *,int,const wchar_t *) LaunchWindows.cpp:233
[UnrealEditor-Win64-Debug.exe] WinMain(HINSTANCE__ *,HINSTANCE__ *,char *,int) LaunchWindows.cpp:284
[Inlined] [UnrealEditor-Win64-Debug.exe] invoke_main() 0x00007ff6082b6e16
[UnrealEditor-Win64-Debug.exe] __scrt_common_main_seh() 0x00007ff6082b6df5
[kernel32.dll] <unknown> 0x00007ff919b97604
[ntdll.dll] <unknown> 0x00007ff91b3826a1

相关链接

**声明:**本文来自公众号:GameDevLearning ,转载请附上原文链接及本声明。

0 Answers