[toc]

# 开篇

虚幻引擎那么厉害的画面,是通过什么样的过程产生的呢? 首先,渲染系统的线程和游戏逻辑的线程是分开的,其次,渲染线程对图像的生成依赖于逻辑线程的 drawCall (提交)。
所以可以认为渲染引擎是附庸于游戏逻辑而存在的。

源码是 4.6

# 1. 获取渲染线程

PreInitPostStartupScreen -> RendringThread.StartRenderingThread() -> FRHIThread::Get().Start();

# FRHIThread (仅用在内部中)

这个类继承自 FRunnable ,Runnable 这个词常用于多线程的环境下,如 Java 中,一个新的自定义线程会封装成一个 Runnable , 这个也类似。 即 UE 中新的线程需要继承 FRunnable 另外,FRHIThread 实际上是 FRunnableThread 封装一层后的类。实际的渲染线程逻辑是在 FRunnableThread 中,而 FRHIThread 在这个版本中只负责了启动以及 获取渲染线程Runnable的全局唯一单例
Get 方法

1
2
3
4
5
static FRHIThread& Get()
{
static FRHIThread Singleton;
return Singleton;
}

获取单例之后就可以开启渲染线程了,表层代码如下:

1
2
3
4
5
6
7
void Start()
{
Thread = FRunnableThread::Create(this, TEXT("RHIThread"), 512 * 1024, FPlatformAffinity::GetRHIThreadPriority(),
FPlatformAffinity::GetRHIThreadMask(), FPlatformAffinity::GetRHIThreadFlags()
);
check(Thread);
}

可以看到,实际渲染线程的 Create 发生在这个函数中。 渲染线程的启动是发生在其创建之后,创建完成的渲染线程会经过 UE 的 TaskGraph 创建一个新的线程 Task 来执行其本身的逻辑。这段代码同样发生在 StartRenderingThread() 函数中。

# GRenderingThreadRunnable - FRenderingThread (非内部全局渲染线程)

如上所述,实际的渲染线程的逻辑包装在 FRenderingThread 中。
在渲染线程启动时,会在全局渲染线程对象指针 GRenderingThreadRunnable 上创建一个新的 FRenderingThread
这段代码同样在 StartRenderingThread() 函数中。其主要流程如下
- 1. Create 创建渲染线程,并赋值给全局指针 - 2. 等待渲染线程创建好,从自己的 TaskGraph 中取出任务并执行。 - 3. 根据线程 ID 注册该渲染线程
- 4. 开启 FRenderingThreadTickHeartbeat ,即心跳更新渲染线程