UEC++ 多线程

一,UE 线程体系

  • 进程:程序的一次运行实例,是操作系统分配资源和隔离的基本单位,一个进程至少有一个线程;
  • 线程:进程内部的执行单元,是 CPU 调度和执行的基本单位;
    • 线程是操作系统调度的独立执行流,线程属于进程,共享进程的地址空间和大部分资源;
  • 并发:同一时间段内处理多个任务,任务交替推进(逻辑上同时处理);
  • 并行:同一时刻同时执行多个任务,真正同时运行(物理上同时执行);
cpp 复制代码
// UE 主要线程类型(分别负责不同任务,运行在 CPU 上)
UE 线程体系
├── 主线程 GameThread (游戏逻辑主线程,Tick、Actor、UObject、蓝图等)  
│    └── 本质:引擎启动时的主线程,非FRunnableThread::Create创建;
│
├── 专用线程(Dedicated Threads)
│   ├── RenderThread (渲染逻辑,负责将场景数据转换为渲染命令)         
│   │   └── FRenderingThread : FRunnable → FRunnableThread::Create
│   ├── RHIThread (负责将渲染命令提交给GPU,可禁用或与Render Thread合并;)           
│   │   └── FRHIThread : FRunnable → FRunnableThread::Create
│   ├── AudioThread (音频混音与播放)       
│   │   └── AudioRenderThread → FRunnableThread
│   ├── LoadingThread (异步加载资源) 
│   │   └── FAsyncLoadingThread : FRunnable → FRunnableThread
│   ├── StatsThread (性能统计)        
│   │   └── FStatsThread : FRunnable → FRunnableThread
│   └── FileI/OThread (文件读写)    
│       └── 通常由平台异步 I/O 或线程池处理,不一定有专用 FRunnableThread;
│
└── 线程池线程(Thread Pool / TaskGraph)
    ├── WorkerThreads (由 TaskGraph / FScheduler 统一管理)
    │   ├── 底层:通过 FRunnableThread 或平台线程封装创建系统线程
    │   ├── 类型:PoolThread、TaskGraphThread 等
    │   └── 用途:AsyncTask、ParallelFor、TaskGraph 短任务
    │
    └── 其他线程池 (逻辑线程池,复用 TaskGraph 工作线程)
        ├── GIOThreadPool
        ├── GBackgroundPriorityThreadPool
        └── GLargeThreadPool
cpp 复制代码
// GPU 运行Shader和计算任务
顶点着色器
像素着色器
计算着色器
几何着色器
细分着色器
光线追踪着色器
GPU 粒子、Niagara GPU 模拟
Lumen、Nanite、虚拟纹理等 GPU 管线
cpp 复制代码
// 渲染一帧流程
// Game Thread         更新游戏逻辑
// Render Thread       收集场景数据,做可见性裁剪,生成渲染命令
// RHI Thread          把命令翻译成图形 API 调用,提交到 GPU 命令队列
// GPU                 异步执行这些命令,跑各种 Shader,渲染出画面
// GPU                 渲染完成后,通知 CPU,交换缓冲区,显示下一帧

UE 渲染一帧
├── CPU:准备与提交 (异步流水线)
│   ├── GameThread (游戏线程)
│   │   ├── Tick 游戏逻辑 (Actor/Component Tick,动画更新,物理模拟,蓝图/脚本)
│   │   ├── 更新场景数据 (变换矩阵,材质参数,骨骼矩阵) 
│   │   └── ENQUEUE_RENDER_COMMAND (把渲染任务推给 Render Thread)
│   ├── RenderThread (渲染线程)
│   │   ├── 可见性裁剪 (视锥裁剪,遮挡剔除,距离裁剪) 
│   │   ├── 图元处理 (Primitive → FMeshBatch)
│   │   ├── 生成 FMeshDrawCommand (按 Pass 分组,绑定 PSO,绑定资源)
│   │   └── 生成 RHI 命令列表
│   └── RHIThread (RHI 线程)
│       ├── 翻译成图形 API 调用 (D3D12,Vulkan,Metal)
│       ├── 录制命令缓冲区
│       └── 提交到 GPU 命令队列
│
├── GPU 命令队列 (按提交顺序排队)
│
├── GPU:渲染管线执行 (RDG 调度)
│   ├── PrePass (深度预计算)
│   │   ├── 顶点着色器绘制几何体
│   │   ├── 计算场景深度
│   │   └── Nanite 路径 (生成 NaniteVisBuffer)
│   ├── LumenSceneUpdate (Lumen 场景更新)
│   │   ├── 收集场景数据
│   │   ├── 更新距离场
│   │   ├── 更新体素结构
│   │   └── 更新表面缓存
│   ├── BasePass (基础 Pass)
│   │   ├── 像素着色器执行
│   │   └── 写入 GBuffer (漫反射,法线,粗糙度,金属度)
│   ├── 光照与阴影
│   │   ├── DiffuseIndirectAndAO (间接光照,环境光遮蔽)
│   │   ├── ShadowDepth (阴影贴图,VSM 虚拟阴影贴图)
│   │   └── Lights (直接光照, 标准延迟光照)
│   ├── 大气与水体
│   │   ├── SingleLayerWater (单层水)
│   │   ├── SkyAtmosphere (天空大气)
│   │   ├── Exponential Height Fog (高度雾)
│   │   └── Volumetric Cloud (体积云)
│   ├── Translucency (半透明)
│   │   ├── 透明材质渲染
│   │   ├── 与扭曲交互
│   │   ├── 与景深交互
│   │   └── 与不透明场景混合
│   └── PostProcessing (后处理)
│       ├── 动态曝光
│       ├── 运动模糊
│       ├── 景深
│       ├── 色调映射
│       └── TSR (超分辨率)
│
├── 最终输出
│   ├── 保存到 BackBuffer (后备缓冲区)
│   ├── UI 绘制
│   ├── 显示引擎 Present
│   └── 显示器显示
│
└── 跨帧流水线 (异步重叠)
    ├── Game Thread:第 N+1 帧
    ├── Render Thread:第 N 帧
    ├── RHI Thread:第 N 帧
    └── GPU:第 N-1 帧

|-------------------------------------|----------------------------------|----------------------------------|
| FRunnable + FRunnableThread | 专用线程,需要完全控制线程生命周期; | 适用于长期运行的后台任务,如渲染、异步加载、网络监听等; |
| AsyncTask | 将任务丢到线程池中异步执行,无需管理线程; | 适用于短小、独立的异步操作,无需创建专用类或线程 |
| TaskGraph | UE 核心任务调度系统,管理着线程池; | 适用于构建复杂的、有依赖关系的任务流,是许多引擎子系统的基础; |
| ParallelFor | 将一个大循环并行化,自动分配到线程池; | 适用于对大型数据集进行相同的独立操作,如遍历数组进行计算; |
| FAsyncTask | 基于 FRunnable 的、可排队的异步任务封装; | 适用于需要在后台执行、并可被任务队列管理(如暂停、取消)的操作; |
| FNonAbandonableTask | 定义不可放弃的任务,强调任务的完成性; | 适用于需要确保一旦开始就必须执行完毕的关键后台工作; |
[UE 多线程方案]

二,FRunnableThread

cpp 复制代码
// 抽象接口,定义一个任务在独立线程上运行的完整生命周期,本身非线程,只是描述线程要执行什么的对象;
// 用于实现自定义多线程任务,将耗时的逻辑放到独立线程中执行,避免阻塞游戏主线程;
class FRunnable
{
public:
	virtual bool Init() { return true; }
	virtual void Stop() { }
	virtual void Exit() { }
	virtual class FSingleThreadRunnable* GetSingleThreadInterface() { return nullptr; }
	virtual ~FRunnable() { }
};
cpp 复制代码
// MyWorker.h
#pragma once
#include "CoreMinimal.h"
#include "HAL/Runnable.h"

class FMyWorker : public FRunnable
{
public:
    FMyWorker();
    virtual ~FMyWorker();

    virtual bool Init() override;
    virtual uint32 Run() override;
    virtual void Stop() override;
    virtual void Exit() override;
private:
    FThreadSafeBool bStopRequested; // 线程安全停止标志
};
cpp 复制代码
// MyWorker.cpp
#include "MyWorker.h"
#include "HAL/RunnableThread.h"
#include "HAL/PlatformProcess.h"

FMyWorker::FMyWorker() : bStopRequested(false) {}
FMyWorker::~FMyWorker() {}

bool FMyWorker::Init() { return true; } // 在此进行初始化,例如分配资源

uint32 FMyWorker::Run() // 这是线程的主要执行体
{
    while (!bStopRequested)
    {
        // 执行你的任务...
        // 例如:处理数据、计算等
        
        // 为避免过度占用 CPU,可以适当休眠
        FPlatformProcess::Sleep(0.01f); 
    }
    return 0;
}

void FMyWorker::Stop() { bStopRequested = true; }
void FMyWorker::Exit() {} // 在此进行清理,例如释放资源
cpp 复制代码
// 启动
FMyWorker* Worker = new FMyWorker();
FRunnableThread* Thread = FRunnableThread::Create(Worker, TEXT("MyWorkerThread"));

// ... 在需要停止时 ...

// 请求停止
Worker->Stop();
// 等待线程结束并释放资源
if (Thread)
{
    Thread->WaitForCompletion();
    delete Thread;
    Thread = nullptr;
}
delete Worker;
Worker = nullptr;
相关推荐
兰亭妙微UI设计公司3 天前
兰亭妙微用户体验设计公司的设计细节:关于提示的那些事
ui·ux·ue
夜猫逐梦3 个月前
【UE源码精读-ActionRPG】GAS基础:能力与效果容器
ue·unreal·ue基础
夜猫逐梦3 个月前
【UE源码精读-ActionRPG】伤害管线:从捕获到扣血
ue·unreal·ue基础
夜猫逐梦4 个月前
【UE基础】03.蓝图与编辑器工作流
编辑器·ue·蓝图·ue编辑器
夜猫逐梦4 个月前
【UE基础】02.基类与蓝图子类的分工
ue·蓝图·ue基础
夜猫逐梦4 个月前
【UE基础】01.环境与引擎心智模型
游戏·逆向·ue·unreal·actionrpg
数峦云数字孪生三维可视化4 个月前
数字孪生可视化架构选型:基于UE像素流送与Web引擎的完整决策指南
数字孪生·ue·web3d·技术选型·像素推流
挨代码4 个月前
UEC++ 数据类型及继承关系
c++·ue
挨代码5 个月前
UE Mobility
ue