UE4初始化过程源码分析

文章详细解析了在Android平台上,从UE4的主入口函数开始,经过一系列复杂的初始化步骤,最终创建并管理EGLContext,包括SingleThreadedContext、RenderingContext和SharedContext的过程,以及多线程渲染的决定因素。
摘要由CSDN通过智能技术生成

       下面的源码以Android平台为例来分析UE4的启动过程(若要了解Windows和Linux平台的话,分析过程大体相似);这里涉及到的源码主要文件如下(文件路径为引擎源码的相对路径):

  • Engine\Source\Runtime\Launch\Private\Android\LaunchAndroid.cpp
  • Engine\Source\Runtime\Launch\Private\LaunchEngineLoop.cpp
  • Engine\Source\Runtime\RHI\Private\DynamicRHI.cpp
  • Engine\Source\Runtime\RHI\Private\Android\AndroidDynamicRHI.cpp
  • Engine\Source\Runtime\OpenGLDrv\Private\OpenGLDevice.cpp
  • Engine\Source\Runtime\OpenGLDrv\Private\Android\AndroidOpenGL.cpp
  • Engine\Source\Runtime\OpenGLDrv\Private\Android\AndroidEGL.cpp
  • Engine\Source\Runtime\Core\Private\Android\AndroidPlatformMisc.cpp
  • Engine\Source\Runtime\OpenGLDrv\Private\Android\AndroidOpenGLPrivate.h

  1. 首先,程序的入口Main函数在Engine\Source\Runtime\Launch\Private\Android\LaunchAndroid.cpp文件中(AndroidMain函数):
  2. AndroidMain函数中,会调用GEngineLoop.PreInit来初始化:
  3. GEngineLoop.PreInit最后会调用到Engine\Source\Runtime\Launch\Private\LaunchEngineLoop.cpp文件中的PreInit函数,如下图:
  4. FEngineLoop类的PreInit函数中会调用PreInitPreStartupScreen函数来初始化:
  5. FEngineLoop::PreInitPreStartupScreen这个函数实现比较复杂,前面会创建UE4中的一些线程等,我们关心的渲染相关的初始化在下面这里的RHIInit函数里面:
  6. RHIInit函数的实现在Engine\Source\Runtime\RHI\Private\DynamicRHI.cpp文件中,其主要通过GDynamicRHI对象的构建和Init来初始化渲染流程:
  7. 我们先看看PlatformCreateDynamicRHI()的实现,Android平台会执行Engine\Source\Runtime\RHI\Private\Android\AndroidDynamicRHI.cpp文件的PlatformCreateDynamicRHI函数: 该函数会调用DynamicRHIModule->CreateRHI来创建DynamicRHI对象:
  8. CreateRHI函数会调用到对应平台的文件(Engine\Source\Runtime\OpenGLDrv\Private\OpenGLDevice.cpp): 这里可以看到主要是new了一个FOpenGLDynamicRHI对象,该类的构造函数实现就在同文件的CreateRHI函数实现的下面紧挨着;
  9. 我们先看FOpenGLDynamicRHI类构造函数中的PlatformInitOpenGL()函数的实现,该函数的实现在Engine\Source\Runtime\OpenGLDrv\Private\Android\AndroidOpenGL.cpp文件中:
  10. 注意到这个函数里面的FAndroidGPUInfo::Get()调用,这个单例调用会构造FAndroidGPUInfo单例对象,看看FAndroidGPUInfo构造函数的实现(实现在Engine\Source\Runtime\OpenGLDrv\Private\Android\AndroidOpenGLPrivate.h文件中):

    到这里,基本就快看到熟悉的EGL窗口的初始化过程了;
  11. 先看看FAndroidAppEntry::PlatformInit()函数实现,这个函数的实现会调用到AndroidOpenGL.cpp文件中的Init: 接着看看这里调用的AndroidEGL对象的Init函数实现;
  12. 跳转到Engine\Source\Runtime\OpenGLDrv\Private\Android\AndroidEGL.cpp文件的Init函数的实现:

    这里基本上就是熟悉的EGLContext的创建,NativeWindow的绑定了;在这里可以看到UE4创建了3个EGLContextSharedContextRenderingContextSingleThreadedContext其中SharedContextRenderingContext是共享的(用于多线程渲染),可以共享纹理、Shader等资源;
  13. 接着回到AndroidOpenGLPrivate.h文件中FAndroidGPUInfo的构造函数,会调用EGL->InitSurface()初始化EGLSurface;这里会创建两个EGLSurface:PImplData->eglSurfacePImplData->auxSurface其中,PImplData->auxSurface会绑定到PImplData->SharedContextPImplData->eglSurface会同时绑定到SingleThreadedContextRenderingContext
  14. 接着FAndroidGPUInfo的构造函数中调用EGL->SetCurrentSharedContext()SharedContext切换为当前线程的渲染上下文
  15. 最后回到FOpenGLDynamicRHI构造函数中,再调用PlatformCreateOpenGLDevice()初始化EGLContext后(初始化时会根据是否使用多线程渲染来选择初始化的Context对象),最后仍然会将当先线程的上下文切换成SharedContext

最后,需要注意,渲染引擎要怎么使用这三个EGLContext,会通过ini配置来确认是否用多线程渲染;Engine\Source\Runtime\Core\Private\Android\AndroidPlatformMisc.cpp文件中的FAndroidMisc::UseRenderThread()函数的返回值来确认是否需要使用多线程渲染;若使用多线程渲染,则AndroidEGL类中用到的GUseThreadedRendering变量将会置为true。若是多线程渲染,则共享Contex为SharedContextRender Context为RenderingContext否则共享Context和Render Context都是SingleThreadedContext

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值