UEC++ 多线程

📅 发布时间:2026/10/20 2:18:00
UEC++ 多线程
一UE 线程体系进程程序的一次运行实例是操作系统分配资源和隔离的基本单位一个进程至少有一个线程线程进程内部的执行单元是 CPU 调度和执行的基本单位线程是操作系统调度的独立执行流线程属于进程共享进程的地址空间和大部分资源并发同一时间段内处理多个任务任务交替推进逻辑上同时处理并行同一时刻同时执行多个任务真正同时运行物理上同时执行// 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// GPU 运行Shader和计算任务 顶点着色器 像素着色器 计算着色器 几何着色器 细分着色器 光线追踪着色器 GPU 粒子、Niagara GPU 模拟 Lumen、Nanite、虚拟纹理等 GPU 管线// 渲染一帧流程 // 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 调用 (D3D12VulkanMetal) │ ├── 录制命令缓冲区 │ └── 提交到 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第 N1 帧 ├── Render Thread第 N 帧 ├── RHI Thread第 N 帧 └── GPU第 N-1 帧UE 多线程方案FRunnableFRunnableThread专用线程需要完全控制线程生命周期适用于长期运行的后台任务如渲染、异步加载、网络监听等FNonAbandonableTaskStub class存根类标记不可放弃的任务强调任务的完成性本身不包含复杂逻辑继承该类的子类需实现DoWork()和GetStatId()适用于需要确保一旦开始就必须执行完毕的关键后台工作FAsyncTask任务对象不会自动销毁需要手动delete可查询任务状态如IsDone()或等待任务完成EnsureCompletion()适合需要更精细控制的场景FAutoDeleteAsyncTask任务执行完毕后自动销毁任务对象适合一次性的后台作业无需手动管理内存Async唯一原生支持返回值返回类型TFutureT的通用异步派发工具会自动销毁需后台计算并拿回结果的场景一次性计算AsyncTask轻量级“即发即忘”快速、无返回值、无需管理后台执行的便捷函数会自动销毁适用于短小、独立的异步操作无需创建专用类或线程一次性计算ParallelFor一个使用 TaskGraph 的通用并行循环将一个标准的for循环自动并行化同步阻塞适用于对大型数据集进行相同的独立操作如遍历数组进行计算TaskGraphUE核心任务调度系统管理着线程池适用于构建复杂的、有依赖关系的任务流是许多引擎子系统的基础二FRunnableThread// 抽象接口定义一个任务在独立线程上运行的完整生命周期本身非线程只是描述线程要执行什么的对象; // 用于实现自定义多线程任务将耗时的逻辑放到独立线程中执行避免阻塞游戏主线程 class FRunnable { public: virtual bool Init() { return true; } virtual uint32 Run() 0; virtual void Stop() {} virtual void Exit() {} // Run()结束时自动调用 virtual class FSingleThreadRunnable* GetSingleThreadInterface() { return nullptr; } virtual ~FRunnable() {} };// 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; // 线程安全停止标志 };// 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() {} // 在此进行清理例如释放资源// 启动 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;