上回书《Part 0 引擎基础》说到,我们粗略地知道UE4是以哪些类来管理一个游戏场景里的数据的,但这仅仅是我们开始探索UE4渲染体系的一小步。

本回主要介绍UE4渲染体系中比较宏观顶层的一部分——多线程渲染,具体的多线程中,又分为:

  • 游戏线程(GameThread)
  • 渲染线程(RenderThread)
  • RHI线程(Render Hardware Interface Thread)

为什么是多线程?

用来描述“渲染”的最基础的理论就是像图上的那样,CPU调用图形API提供的DrawCall命令(也叫绘制指令),在命令中说明需要渲染的数据、属性等等,然后CPU等待GPU返回渲染结果,完成渲染。对于那些渲染频率不高的场景,这种方式并没有什么问题,但在游戏这种需要实时性渲染的高频率场景下,问题就显现出来了。

游戏引擎完成渲染不只有提交DrawCall这一个任务,除了这个以外,CPU要花费非常多的时间在处理游戏逻辑运算和准备渲染数据上,比如处理用户的输入、执行游戏脚本、更新物理和动画、可见性剔除等等等等。

假如引擎把所有的事都交由GameThread来完成,当GameThread把当前这一帧该做的事都做完了,准备好要渲染的数据,提交到GPU后,GameThread就只能等待渲染结果,但GameThread接受到当前这一帧的用户输入后,完全可以去执行下一帧的各种任务,但单线程的机制并不允许这样的事情。

多核心的CPU和多线程并发并行的操作系统在今天已经不是什么稀罕事了,将与渲染相关的任务从GameThread中剥离出来,让GameThread专注处理游戏逻辑上的的各种计算任务,让RenderThread专门和GPU来完成渲染任务,就成了自然而然的事情。

加入RenderThread后,每次GameThread处理完各种任务,准备好渲染数据,把数据发送给RenderThread,然后就继续处理下一帧的任务了,RenderThread收到数据,进行一些数据处理后(比如可见性剔除),向GPU提交DrawCall,等待渲染结果,完成渲染。

那RHIThread是什么呢?UE4中RHI的提出可能有很多原因:

  • 支持跨平台多种图形API
  • 并行提交DrawCall
  • 其他各种各样的性能优化

首先是针对跨平台多种图形API,由于不同平台支持的图形API不同,Windows限定的Direct3D、MacOS限定的Metal以及跨平台(包括移动端)的OpenGL和Vulkan,在有RHIThread之前,RenderThread会根据不同的图形API来选择DrawCall,这肯定会增加不少工作量,维护也更加复杂。

"All problems in computer science can be solved by another level of indirection." —— Jay Black

如果把这件事交由单独的一个线程来做,岂不美哉?这不,RHIThread就来了。

RenderThread准备好渲染数据后,向RHIThread提交一个与图形API无关的RHIDrawCommand,RHIThread掏出来一个表,查找当前平台的图形API里哪一句是对应的DrawCall,然后再向GPU提交DrawCall,等待渲染结果,完成渲染。这样一来,RenderThread就可以在自己的任务上专注(方便优化),在RHIThread上完成对各个平台的图形API版本迭代维护。

当然这是从工程优化角度上RHIThread存在的理由,当然RHI还有一些更加直接的存在理由,那就是为了支持并行化提交DrawCall。在一些比较旧的图形API里,DrawCall都是阻塞的,即一个线程提交DrawCall时,不允许其他线程提交。图形API调用GPU计算后,GPU本身计算渲染是需要时间的,而在这时间里,图形API如果能准备好下一次DrawCall,那必然是更好的。

随着技术更新,一些新的图形API开始提供一些并行化提交DrawCall的方式,在没有RHI的时候,难道让UE4跑多个RenderThread吗?好像也不太合理,RenderThread里面除了提交DrawCall的其他部分也不需要多个线程来完成,那需要单独提出来多线程化的任务就顺理成章地变成了RHIThread了。

总结

可以看到UE4渲染体系中多线程渲染的设计并不是一开始就是这样,而是跟随着技术的需求在不断发展进步的(新的UE5里面估计又改了不少了)。

本回并没有着重讨论各种线程内部细节的任务,也没有非常深入的讲解各个线程之间是如何传递具体的命令和数据的,因为讲起来那篇幅真的就太长了,之后再慢慢地整理吧,网络上的资料也很多,大家可以自行拓展阅读。

参考文献

《图解UE4渲染体系》Part 1 多线程渲染的更多相关文章

  1. BGFX多线程渲染

    BGFX多线程渲染 1. 多线程基础 1. 并发概念 1. 并发任务简介 在多年以前,在手机.pc端.游戏机等,都是一个单核的CPU.这样,在硬件层面上,处理多个任务的时候,也是把一些任务切分成一些小 ...

  2. 《图解UE4渲染体系》Part 0 引擎基础

    在介绍UE4渲染体系前,我们有必要来先看一下UE4是用什么样的方式来构建游戏场景数据的. 1 Object 在UE4中当我们说Object,通常是指代引擎代码中的UObject类,它是引擎里管理绝大部 ...

  3. 剖析虚幻渲染体系(06)- UE5特辑Part 1(特性和Nanite)

    目录 6.1 本篇概述 6.1.1 本篇内容 6.1.2 基础概念 6.2 UE5新特性 6.2.1 UE5编辑器 6.2.1.1 下载编辑器及资源 6.2.1.2 启动示例工程 6.2.1.3 编辑 ...

  4. 剖析虚幻渲染体系(10)- RHI

    目录 10.1 本篇概述 10.2 RHI基础 10.2.1 FRenderResource 10.2.2 FRHIResource 10.2.3 FRHICommand 10.2.4 FRHICom ...

  5. 剖析虚幻渲染体系(11)- RDG

    目录 11.1 本篇概述 11.2 RDG基础 11.2.1 RDG基础类型 11.2.2 RDG资源 11.2.3 RDG Pass 11.2.4 FRDGBuilder 11.3 RDG机制 11 ...

  6. 剖析虚幻渲染体系(12)- 移动端专题Part 1(UE移动端渲染分析)

    目录 12.1 本篇概述 12.1.1 移动设备的特点 12.2 UE移动端渲染特性 12.2.1 Feature Level 12.2.2 Deferred Shading 12.2.3 Groun ...

  7. 剖析虚幻渲染体系(12)- 移动端专题Part 3(渲染优化)

    目录 12.6 移动端渲染优化 12.6.1 渲染管线优化 12.6.1.1 使用新特性 12.6.1.2 管线优化 12.6.1.3 带宽优化 12.6.2 资源优化 12.6.2.1 纹理优化 1 ...

  8. 剖析虚幻渲染体系(13)- RHI补充篇:现代图形API之奥义与指南

    目录 13.1 本篇概述 13.1.1 本篇内容 13.1.2 概念总览 13.1.3 现代图形API特点 13.2 设备上下文 13.2.1 启动流程 13.2.2 Device 13.2.3 Sw ...

  9. 剖析虚幻渲染体系(14)- 延展篇:现代渲染引擎演变史Part 1(萌芽期)

    目录 14.1 本篇概述 14.1.1 游戏引擎简介 14.1.2 游戏引擎模块 14.1.3 游戏引擎列表 14.1.3.1 Unreal Engine 14.1.3.2 Unity 14.1.3. ...

随机推荐

  1. bash shell 中的 hash 命令有什么作用?

    linux 命令'hash'管理着一个内置的哈希表,记录了已执行过的命令的完整路径,用该命令可以打印出你所使用过的命令以及执行的次数. [root@localhost ~]# hashhits com ...

  2. springboot的核心配置文件

    一.springboot主要配置文件种类 1.bootstrap (.yml或.properties) 2.application(.yml或.properties) 二.bootstrap与appl ...

  3. 使用过 Redis 做异步队列么,你是怎么用的?

    答:一般使用 list 结构作为队列,rpush 生产消息,lpop 消费消息.当 lpop 没有 消息的时候,要适当 sleep 一会再重试. 如果对方追问可不可以不用 sleep 呢? list ...

  4. kafka 分布式(不是单机)的情况下,如何保证消息的顺序消费?

    Kafka 分布式的单位是 partition,同一个 partition 用一个 write ahead log 组织, 所以可以保证 FIFO 的顺序.不同 partition 之间不能保证顺序. ...

  5. memcached 和服务器的 local cache(比如 PHP 的 APC、 mmap 文件等)相比,有什么优缺点?

    首先,local cache 有许多与上面(query cache)相同的问题.local cache 能够利 用的内存容量受到(单台)服务器空闲内存空间的限制.不过,local第 109 页 共 4 ...

  6. Linux重启网卡服务Failed to start LSB: Bring up/down networking.

    Linux网卡重启失败,使用 systemctl status network.service命令进行查看状态,发现启动有异常产生 network.service: control process e ...

  7. 自动驾驶运动规划-Dubins曲线

    1.Simple Car模型 如下图所示,Simple Car模型是一个表达车辆运动的简易模型.Simple Car模型将车辆看做平面上的刚体运动,刚体的原点位于车辆后轮的中心:x轴沿着车辆主轴方向, ...

  8. 分压杯频LLC变换器

  9. stylus css tooltips 工具提示

    tooltips 纯css工具提示 bubbles-tooltips 查看效果 演示 安装 npm install tooltips --save 使用 在 gulp 中使用 gulp var gul ...

  10. 聊聊 DisplayObject 的x/y/regX/regY/rotation/scale/skew 属性

    首先要指出的是:DisplayObject 实例的属性<x, y> 与 graphics.draw*(x, y, ...) 的参数<x, y>没有关系. 在原生的 Canvas ...