August 16, 2019

游戏引擎中的资源生命期管理问题

最近我们开发中的游戏引擎在修理资源管理模块中的 bug 时,我提出了一些想法,希望可以简化资源对象的生命期管理。

其实这个模块已经被重构过几次了。我想理一下它的发展轨迹。

最开始,我们不想太考虑资源的生命期问题,全部都不释放。当然,谁都明白,这种策略只适合做 demo ,不可能用在产品中。

因为我们整个引擎的框架是用 lua 搭建,那么,最直接的想法就是利用 lua 自带的 gc 来回收那些不被引用的资源对象。我不太喜欢这个简单粗暴的方法。因为首先, gc 不会太及时,其次 gc 方法触发的时机很难控制,容易干扰正常的运行流程。图形显示模块是时间敏感的,如果因为资源释放占用了 cpu 的话,很容易变成肉眼可查的卡顿。

另一个促使我们认真考虑资源管理模块的设计的原因是,当我们从 demo 过渡到现实世界的大游戏场景时,过多的资源量触发了 bgfx 的一个内部限制:如果你在一个渲染帧内调用了过多资源 api (例如创建新的 buffer texture 等),会超出 bgfx 的多线程渲染内部的一个消息管道上限,直接让程序崩溃。

所以我们不得不比计划提前实现资源的异步加载模块,它属于资源管理模块的一部分,所以也就顺理成章的考虑整个资源管理模块的设计。

阅读全文 "游戏引擎中的资源生命期管理问题" »

August 02, 2019

资源文件的转换问题

我们上周在游戏引擎上面的工作中遇到一些 bug ,涉及到过去的一些设计问题。维持讨论了几天解决该问题的方案。今天终于把最终方案确定了下来,值得做一个记录。

bug 出在游戏资源文件的转换上面。

游戏里用到的资源通常需要一个导入资源库的过程,例如你的原始贴图是一个 png 文件,但是引擎需要的是对应运行平台的压缩格式,windows 上是 dxt ,手机上是 ktx 等等。这个过程,在 Unity 等商业引擎中,是放在资源导入流程中。

我们的引擎把这个转换过程放在虚拟文件系统这个层次。这个设计决策是因为,我感觉统一导入资源是个痛点,用的人通常需要等待导入过程。Unity 用了 cache server 来解决这个痛点,但我认为 cache server 也存在一些设计问题 ,这个会在后面再展开一次。

我更希望转换过程是惰性的,直到最终运行需要的资源才需要转换。

阅读全文 "资源文件的转换问题" »

July 24, 2019

程序员应该怎样提高自己

经常有小(我 20 岁左右的)朋友问我,作为一个程序员该怎样提高自己。每个人的经历不同,所处环境不错,其实这个问题很难具体回答。不如好好写一篇总结,以后就不必每封 email 都重新写一次了。

纵观我近 30 年的编程生涯,在每个时期,我看到的东西都不同。想必再过 10 年还会有变迁。我只能写写当下眼界所及之处。

阅读全文 "程序员应该怎样提高自己" »

July 17, 2019

法线贴图的压缩格式比较

这几天一直在忙着在 bgfx 上增加 ASTC 格式的法线贴图支持

法线贴图上的法线向量虽然有三个分量,但是它们是归一化的。而且,切线空间上的法线贴图的第三个向量 Z 总是正值,所以我们只需要用两个分量就可以保存下法线信息,在运行时再计算出第三个向量。

不过这种方法有一个问题,贴图采样的时候,由于是线性插值,所以计算出来的第三个向量可以和实际差的较远。通常的解决方法是保存球形投影的 X Y 分量,减少 Z 的偏差。具体可以看看 Nvidia 的这篇 Real-Time Normal Map DXT Compression

显卡硬件一开始并不支持的双通道压缩贴图,所以最早使用这个算法的 Id 是用 dxt5 模拟的,使用 Dxt5 的 RGB 中的 G 保存一个通道,再用 A 保存另一个通道。后来的 EAC_RG11 则直接支持了双通道压缩贴图。

ASTC 虽然没有特别支持双通道贴图,但是它的 encoder 可以把信息权重放在两个通道上,这样就可以在同样的 bpp 下,让双通道信息的误差更小。

bgfx 自带的贴图压缩工具没有支持这样的压缩参数,我最近的工作就是完善它。

阅读全文 "法线贴图的压缩格式比较" »

July 08, 2019

用 skynet 实现 unity 的 cache server

我们公司的一些 Unity 项目,当 cache server 的数据上涨到几百 G 后,经常遇到问题。最近一次是 nodejs 内存使用太多导致进程挂掉。

我不太想的明白,一个几乎不需要在内存中保留什么状态的服务,为啥会吃掉那么多内存。简单看了一下 cache server 的官方实现 感觉实现的挺糟糕的。它的业务很简单,还不如按协议自己实现一个。

阅读全文 "用 skynet 实现 unity 的 cache server " »

June 20, 2019

字符串比较用 id 管理策略

前两天写了 快速字符串对象比较 ,我把这个想法提交到 Lua 的邮件列表,建议 Lua 的未来版本去掉长短字符串,不做 string interning ,用这个方法解决字符串比较的性能问题。Lua 的主要维护者 Reberbo 表示了兴趣,同时也提出了几点问题。

其中一个问题是,Lua 未必运行在 64bit 平台上,所以并没有直接使用 64bit 整数类型。而如果使用 32bit id 就无法简单的通过自增来保证 id 永远唯一。

我就这个问题考虑了几天,提了好几个解决方案,其中一个方案我最为满意,在这里重新用中文记录一下。

阅读全文 "字符串比较用 id 管理策略" »

June 17, 2019

快速字符串对象比较

这段时间在想办法解决多个 lua 虚拟机间共享对象的问题。这里的一个核心问题是,lua 的短字符串做了 interning ,虚拟机在比较两个字符串时只需要比较字符串对象指针即可。而多个 lua vm 如果想共享数据,必须解决这个问题。前段时间实现的 并发 Hash Map ,和 共享表 就是在这方面做的努力。

随着 lua 5.4 的临近,我最近尝试了在 lua 5.4 的 alpha 版上做类似的 patch 。但是 lua 5.4 对 gc 的修改极大,这让我尝试去找其它的办法来做这件事。

我觉得,如果允许 vm 在处理短字符串比较时,不严格遵守 interning 的约定,那么就不再需要对 gc 流程做改造了。这样,从外部共享来的字符串,只要做全量值比较,依然可以得到正确的结果。

这样的修改固然对 lua 的代码影响极小,但很可能会有很大的性能损失。毕竟,字符串比较从原来的 O(1) 一次指针比较,变成了复杂得多的 memcmp O(n) 。而这明显是 vm 的性能瓶颈所在。

阅读全文 "快速字符串对象比较" »

Misc

Categories

Archives

Recent Comments