腾讯游戏学院-----游戏引擎中的多线程和内存管理【笔记二】

文章仅记录部分内容作为笔记,对视频感兴趣的可见下面链接的原视频:

https://gameinstitute.qq.com/course/detail/10119

课程目录:

【第一章】内存

      - 游戏机内存演化历史
      - 游戏引擎内常用的内存分配器介绍
      - 面向数据的设计方法
      - Entity Component System


【第二章】多线程

      - 主/渲染线程结构
      - 任务系统

 

正文:

【第二章】多线程:

一、主/渲染线程结构

关于游戏引擎的发展史暂时不记录。

视频中提到的顽皮狗公司关于神秘海域中多线程设计的结构,关于渲染计算中,比如LIGHTING部分,将其放到了SPU上;

其实我之前也在阅读一本书,是《游戏引擎架构》,因为个人原因,那本书没来得及记录笔记,但是已经阅读了一部分。

https://book.douban.com/review/6707556/

上面链接中的评论说的很好。作者也是顽皮狗的自身开发者,参与了《神秘海域》系列和《最后生还者》此类高品质游戏,如果对这方面感兴趣的,强推这本书,不过书本身较厚,需要一定时间来进行阅读。

视频中是以《天刀》为例子。

渲染线程分离(背景)

  • GR1 Demo里 90%的CPU时间花在渲染模块。

使用的渲染pipeline是一个传统的渲染模型

  • 做功能扩展和修改是困难重重

希望使用更加先进的基于物理光照模型,会面临一些列问题(复杂度会随着代码量的增加而愈发困难)

  • 需求结构更好,效率更高的渲染模块

常见的游戏多线程架构设计

一般是分为一个主线程,这个主线程是用来处理输入,物理,后处理(例如依赖于动画和物理全部处理完之后的操作);还有其他的一些worker线程,用来做IO或者动画,然后渲染线程。

但是这种架构属于一种理想架构,会出现线程等待,类似操作系统中的造成阻塞?这种WAIT和IDLE都会造成整体性能的阻塞。

渲染线程分离(实现)

  • 关键点

状态区分(逻辑状态和渲染状态),如何有效的把这两个数据进行区分?

状态切换(渲染状态送入渲染线程),如何将相关内容,更有效的送入到对应线程来执行

  • 核心结构(以天刀举例)

GraphicAsyncData(状态区分)

SyncBarrier/SyncZone(状态切换)

SyncBarrier--线程同步点,只有所有线程都到达才能够继续执行。

SyncZone--在该时间范围内,只有一个线程能够执行。

  • Hybrid

即包含了StateBuffer(GraphicAsyncData)

  • 技术选择(天刀举例)

UE系 基于RenderCommand的RingBuffer,最简单的方式就是:找到对象,设置状态,然后交给GPU处理,以此类推。当你想把这个东西用多线程来实现,一个简单的想法就是把状态拷贝,把他放在一个数组里,这个数组就是RingBuffer。当你一直向RingBuffer里输入状态,另外一个线程会一直处理这个数据,这个就是渲染线程。

这个设计就会造成一个Producer Consumer(生产者消费者问题,这个应该都懂)的问题,有时候主线程会快,渲染线程会慢,或者反过来。一旦出现二者速度不同,必然有一个线程会等待。

Halo系 基于GameState的DoubleBuffer,最简单的方式就是可以把所有的状态都放在一起,例如一个结构体,里面既有逻辑状态也有渲染状态。

最早Halo体是把渲染状态,逻辑状态都存起来,但是存两份,然后在每一帧结束的时候,把这两份的指针交换一下,然后下一帧重新去写。

好处就是在渲染线程,它拿到了游戏逻辑上一帧的完整状态。缺点是相当于把你所有游戏运行时的内存同步的复制了一份,就是说有很大的内存开销。

当时要这么做的原因是很多游戏要做实时存储。

 

二、JobSystem(任务系统)

任务系统(积累)

Frostbite2

  • Parallel Future of a game Engine

Naughty Dog

  • Lighting and shading in Uncharted2

 

举例:

碰撞检测

碰撞检测的特点是,它的场景,特别是静态场景都是非常固定的,数据结构检查算法也是统一的,也就是说,假设一帧想做N个碰撞检测。完全可以放到N个盒上去执行。

寻路

和上面相同,场景固定,算法固定,各算法之间不产生依赖关系,很容易做多线程。

光栅化和遮挡检测

避免送过多不必要的东西给GPU,如果能被完全遮挡,那证明这个东西暂时就不需要送个GPU。

光栅化也是完全可以作为多线程来处理的。

粒子系统的更新

动画蒙皮的更新

 

任务系统(举例):

  • Windows--Parallel Programming Library/ConcurrencyRuntime
  • Apple--Grand Central Dispatch(libdispatch)
  • Intel TBB
  • HPX

任务系统的简单实现形式:

经典的单TaskQueue--当产生一个任务时,这个任务会送入DQ,如图,有很多个THREAD跑在CP的核上,它们就会竞争从QUeue里获取任务。

局限性:

对Queue的访问是一个有锁的操作,每个线程不得不等待才能获得object的访问(操作系统中学习过的内容),每个Task之间可能还存在依赖关系。

后续内容不做记录。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值