调试android的时候比较好奇,如何选择图形API是vulkan还是openGL ES,所以看了一下。其实RHI(Rendering Hardware Interface)初始化的逻辑非常简单,估计读过UE4源码的都清楚。我也就在这里给没有研究过的朋友简单叙述一下吧。

unreal engine 4 图形API选择逻辑(RHI初始化逻辑)

       UE4引擎RHI初始化的阶段,在引擎的preInit阶段,执行RHIInit函数。而RHIInit函数中真正与平台相关的是PlatformCreateDynimicRHI函数。每个平台要实现对应自己的PlatformCreateDynimicRHI函数。

HTML5

       从最简单的HTML5平台开始讲起吧。

       HTML5DynimicRHI的逻辑非常简单,因为只支持openGL ES API(es2,UE4暂时不支持webgl2),所以直接启用OpenGLDrv RHI即可。

Windows

       Windows平台RHI初始化逻辑最为复杂(windows平台支持图形API数量最多,featurelevel也最多)。

1. 判断命令行参数

  1. 使用的featurelevel: sm4, sm5
  2. 使用的图形API:
    • vulkan:vulkan
    • openGL: opengl, opengl3, opengl4
    • directx: d3d10, dx10, d3d11, dx11, d3d12, dx12

命令行参数中指定API的优先级最高,如果没有编译对应shader,会cache错误直接崩溃

2. 如果命令行参数中没有指定API

       如果如果命令行参数中没有指定API,会在 DefaultEngine.ini 配置文件中寻找[/Script/WindowsTargetPlatform.WindowsTargetSetting]中的TargetedRHIs配置,从上往下第一个支持的API就是RHI实际使用的图形API,featurelevel会使用所支持最大的featurelevel。

       Windows平台最后还要判断一下驱动支持情况,还有一种特殊情况,运行fraps的时候,dx11和dx12的RHI会初始化失败,原因不明,但是UE4源码中有提。

还有一个需要注意的地方,Windows上的DX和Xbox one上的DX并不完全相同

Android

       Android平台RHI初始化逻辑就要简单的多,能用vulkan的就用vulkan,用不了的就用openGL ES。用vulkan时featurelevel也是es31。

       运行PlatformCreateDynimicRHI时会先执行FAndroidMisc::ShouldUseVulkan(),为true就用vulkan,否则就openGL。

       FAndroidMisc::ShouldUseVulkan()首先会检查CVars r.Android.DisableVulkanSupport,如果为1就强行不使用vulkan。

       之后是在 DefaultEngine.ini 配置文件中寻找[/Script/AndroidRuntimeSettings.AndroidRuntimeSettings]中的bSupportVulkan配置,为0则不使用vulkan。

       如果ShouldUseVulkan()为true,会尝试启动VulkanRHI,如果VulkanRHI则后备启动OpenGLDrv

在支持vulkan的设备上vulkan初始化失败的情况我还真遇到过,在华为mate9(mali-G71 mp8)上开MGD的情况下失败

Apple(mac os & iOS)

mac os

       mac os平台上现在初始化逻辑非常简单,因为UE4已经不在osx上支持openGL RHI,只支持metal,支持的命令行参数有metal, metalsm5, 但其实输不输已经无所谓了。

       如果没有命令行参数就检查[/Script/MacTargetPlatform.MacTargetSetting]中的TargetedRHIs配置,接下来逻辑和Windows相同,不过考虑UE4在osx现在只支持metal。。。

iOS

       iOS也会检查命令行参数。

使用的图形API:

       之后是在 DefaultEngine.ini 配置文件中寻找[/Script/IOSRuntimeSettings.IOSRuntimeSettings]中的bSupportMetalMRT配置,为1则使用metal MRT。

       之后是在 DefaultEngine.ini 配置文件中寻找[/Script/IOSRuntimeSettings.IOSRuntimeSettings]中的bSupportMetalMRT配置,为1则使用metal MRT。

       在不使用metal MRT的情况下,在配置中寻找bSupportMetal,为1则使用metal(无MRT)。

       在不使用metal的情况下,在配置中寻找bSupportOpenGLES2, 为1则使用openGL ES 2.0。(iOS不支持openGL ES 3.1)

不支持metal的iOS设备已经非常稀少,现阶段在iOS上可以完全no openGL,only metal

Linux

       Linux上RHI初始化逻辑也比较简单,如果命令行参数中有vulkan就使用VulkanRHI,没有就使用OpenGLDrv

       [/Script/LinuxTargetPlatform.LinuxTargetSetting]中的TargetedRHIs配置只和使用shader的格式相关(高版本的openGL也支持使用SPIR-V作为shader)。

Linux上featurelevel只支持SM5

小结

       用张流程图简单总结一下。

RHIInit