

游戏引擎中的资源生命期管理问题
source link: https://www.tuicool.com/articles/mQZFry3
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近我们开发中的游戏引擎在修理资源管理模块中的 bug 时,我提出了一些想法,希望可以简化资源对象的生命期管理。
其实这个模块已经被重构过几次了。我想理一下它的发展轨迹。
最开始,我们不想太考虑资源的生命期问题,全部都不释放。当然,谁都明白,这种策略只适合做 demo ,不可能用在产品中。
因为我们整个引擎的框架是用 lua 搭建,那么,最直接的想法就是利用 lua 自带的 gc 来回收那些不被引用的资源对象。我不太喜欢这个简单粗暴的方法。因为首先, gc 不会太及时,其次 gc 方法触发的时机很难控制,容易干扰正常的运行流程。图形显示模块是时间敏感的,如果因为资源释放占用了 cpu 的话,很容易变成肉眼可查的卡顿。
另一个促使我们认真考虑资源管理模块的设计的原因是,当我们从 demo 过渡到现实世界的大游戏场景时,过多的资源量触发了 bgfx 的一个内部限制:如果你在一个渲染帧内调用了过多资源 api (例如创建新的 buffer texture 等),会超出 bgfx 的多线程渲染内部的一个消息管道上限,直接让程序崩溃。
所以我们不得不比计划提前实现资源的异步加载模块,它属于资源管理模块的一部分,所以也就顺理成章的考虑整个资源管理模块的设计。
我们一开始实现了一个中规中矩的引用计数方案。资源永远都被 ECS 中的 C 引用,且永远没有对外引用,所以并没有循环引用的问题。引用计数一定可以正确的管理资源的生命周期。一旦引用计数为 0 ,把课回收资源放到一个集合里,交给一个 system 处理即可。
但我直觉上不喜欢在一个基于 lua 这样自带 gc 的语言构建的框架中使用一个蹩脚的引用计数机制。而且,移动设备是一个内存受限的环境,我认为基于业务上不再对资源引用与否来觉得是否可以释放资源不是最好的管理方式。
我认为可以把资源分为两类:一,从 IO 获取的资源,它们有唯一的名字(文件名)。这类资源即使从内存释放,也可以重新加载回内存。二,根据其它数据由代码生成的资源,如果销毁不太容易重建。
第一类资源是大头,我认为它们实际上可以随时从内存销毁,释放内存供其它使用。部分资源类型还有替代方案:例如贴图,我们可以用统一空白贴图临时顶替使用。
针对第一类资源,生命期管理就不必基于它是否在内存中还有引用决定,而应该由是否很久没有使用决定。一个长期未使用的资源对象,无论在 ECS 中是否还有 C 对其引用,资源管理模块都有权销毁它,直到下次使用它时再通过异步加载模块读回。
而第二类资源就麻烦一些。如果我们随意删除,就很难重建(因为失去了当初创建它的上下文)。我们决定在内存富裕的情况下,永远保留这类资源。在迫不得已的时候,再在条件允许时删除它。最早的实现又用回了引用计数方案,但很快又去掉了。我们的 ECS 框架很容易遍历所有的资源,所以在必要的时候确定一个资源对象是否还有 C 在引用并不复杂。所以不必额外做繁杂的加减引用操作。
后来,在经过一些讨论后。我又从 imgui 的设计中得到了新的灵感:
其实,当初我们也考虑过给每种第二类资源提供一个回调函数,在销毁后调用一下就能重建回来。但并不是总能简单的写出这个创建函数。例如,如果一张贴图是用场景上的一个摄像机渲染出来的,那么这个回调函数就涉及相关场景对象了。一个简单的闭包函数很可能破坏掉 ECS 的设计原则。
但是,如果我们反过来想,如果每帧都主动创建这种资源呢?好比 imgui 并不保存控件的状态,每帧都去画一下那个控件一样。这样就不会影响 ECS 的设计原则,可以用自然的方式去创建动态资源。之后,我们就可以再这个基础上 cache 上一帧的结果,而避免每帧都创建。
这样设计后,第二类资源对象就和第一类对象一样,可以在任意时刻销毁。资源管理模块只需要按 LRU 算法淘汰超出内存阙值的资源就够了。
Recommend
-
27
-
14
精彩回顾 |【第41期CXO直播间】Synopsys 软件开发全生命周期管理战略安全说精彩回顾 |【第41期CXO直播间】Synopsys 软件开发全生命周期管理战略安全说 2020-12-17 15:25:32 来源:CIO时代网 VUCA...
-
9
神策数据孙文亮:客户全生命周期管理从方法到实践全解析 神策小秘书...
-
13
一、前言 在 Elasticsearch 的日常中,有很多如存储 系统日志 、 行为数据...
-
7
K8s 中生命周期管理设计模式由云原生平台管理的容器化应用对其生命周期没有控制权,要想成为优秀的云原生化 ,它们必须监听管理平台发出的事件,并相应地调整其生命周期。托管生命周期模式描述了应用程序如何能够并且应该对这些生命周期事件做出反应。 ...
-
9
API 生命周期管理是一个术语,是指需要管理的 API 整个生命周期中从创建到报废的所有步骤。API数量正在激增当中,因为它们是数字业务的关键。公司面临的主要挑战是通过以下方式来应对日益增长的新API需求。 迅速创建API 通过管理目...
-
13
本文预计阅读时间 13 分钟 索引生命周期管理将会是es维护管理中重要的一环,生产中已经有一个集群用的 7.x 版本,一直也没有使用自带的生命周期管理工具,今天就来研究一下,现在先通过简单的例子来理解这个功能以及用法。 1,...
-
9
1)如何管理大型游戏的美术资源工程 2)Google Play强制64位App相关问题 3)零散AssetBundle资源再打包疑问 4)Unity中Api Compatibility Level .net 4.x与.NET Standard 2.0的区别 5)Unity 2020版本OpenGL ES3下SRP Batcher失效问题...
-
5
elasticsearch 学习系列目录——更新ing二、问题描述GET _cat/tasks?v action task_id parent...
-
5
渲染引擎的资源加载优化 针对一个渲染引擎的性能,最主要的当然是实时渲染的帧率。另一方面,对于轻型的引擎来说,用户不会对场景加载 保有一个较长的加载时间的心理预期,最好是,点击按键,瞬间整个场景出现,毕竟轻量...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK