July 12, 2018

数学运算的实时编译及 Lua 中的一点奇技淫巧

我为 3d engine 项目设计的向量运算库 已经用了一段时间了。在使用过程中也一直在改进 。从一开始,我就考虑过,这个库的设计主要考量是减少 lua 和 C 交互间的开销,提高内聚性。而易用性方面,计划再上面再做封装。这段时间继续在想怎样从更自然的表达形式转换到这个库的逆波兰指令流上。

大致的方向有两个:

其一,实现一个小语言,用字符串输入表达式组。

其二,利用 Lua 已有的语法解析设施,把 lua 的一个函数翻译成对应的数学运算指令流。

两者都可以看成是一种 jit 的过程,在第一次运行的时候,做一些翻译工作,把要进行的数学运算打包成 C 代码可以处理的指令流,或翻译成现有数学库支持的指令流;或者,增加一个 lua 源码的预处理流程,在预处理阶段做好编译工作(aot)。

这个需求可以分解成三个问题:

首先,如何把更易用的的源码对接到 lua 原生代码。

其次,如何转换为正确的数学运算指令流。

最后,为以上过程选择 jit 或 aot 集成。

阅读全文 "数学运算的实时编译及 Lua 中的一点奇技淫巧" »

July 06, 2018

线程安全的 log 回调函数

最近在做 3d engine 时发现,我们使用的渲染 api 库 bgfx 提供的 log 回调函数是需要自己保证线程安全的。也就是说 bgfx 有可能在不同线程(采用多线程渲染时)调用这个 log 回调函数。

如果回调函数仅仅只是把 log 串写入文件(例如标准输出),那么可以由 crt 本身来保证线程安全。但如果想自己处理 log ,例如把 log 串压回 lua 虚拟机,那么就必须自己负责线程安全的问题。

阅读全文 "线程安全的 log 回调函数" »

June 20, 2018

有时候还真要信命

我们公司最近预研了一款对战游戏,是我的创新实验室中一个同事原创的玩法,同时他做了几乎所有的实现工作:包括客户端,服务器,还有从别的老项目借出来的美术资源……

在独自开发了大半年后,我们又加了几个同事协助他把最后的工作完成。上个月,终于告一段落,所以在公司内部做了一次大规模的试玩。游戏还是挺有意思的,试玩的同学非常踊跃,昼夜不休的打天梯。试玩期结束后,我们决定对最活跃的数十个玩家进行一次奖励。用抽奖的形式奖励自选 switch 游戏卡。天梯排名靠前的同学可以有更高的权重(是排名靠后的同学的 6 倍)。我的排名很低,所以只拿了一张抽奖票,最后一共发放了 106 张奖票。

阅读全文 "有时候还真要信命" »

June 10, 2018

群星的汉化及官方中文版

前段时间,Stellaris (群星)在 steam 上招到了大量差评。这款被短时间差评也不是第一次了,最猛烈的一次是因为 2.0 版改动太大,简直成了款新游戏,得罪了大量 100 小时游戏时间以上的老粉丝;我记得还有一次是因为涨价;似乎还有一次,原因不太记得了。

而这次,是因为有中国玩家用英文在官方论坛请求游戏加入官方中文,被客服不客气的回绝了。原本没官中就差评就是我朝玩家的时尚之一,而这次直接被官方怼回来,更是刺激了我朝玩家的 G 点,连那些平常不参加无官中就差评的玩家都爆了许多。

还是太年轻了。如果是 20 年前,我估计也会义愤填膺的。那年我朝南斯拉夫大使馆被炸,我还在网上乱吼过几句呢,谁没当过愤怒的少年呢?

阅读全文 "群星的汉化及官方中文版" »

May 26, 2018

跟踪 skynet 服务间的消息请求及性能分析

skynet 中每个服务都是独立 lua 虚拟机,虽然服务间相互发起请求很容易,但业务复杂后,追踪业务逻辑却很麻烦。

我最近给 skynet 加了一个 skynet.trace() 命令,可以开启对当前执行序的跟踪统计。比如,在 example 的 agent 服务中,我们在每条 client 发起的请求处理时调用一次 skynet.trace() 就会得到下面这样的 log :

[:01000012] <TRACE :01000012-5> 9563528587255135 trace
[:01000012] <TRACE :01000012-5> 9563528587272881 call : @./examples/agent.lua:17 @./examples/agent.lua:36 @./examples/agent.lua:58
[:0100000d] <TRACE :01000012-5> 9563528587326048 request
[:0100000d] <TRACE :01000012-5> 9563528587344784 response
[:0100000d] <TRACE :01000012-5> 9563528587352027 end
[:01000012] <TRACE :01000012-5> 9563528587367443 resume
[:01000012] <TRACE :01000012-5> 9563528587423140 end

阅读全文 "跟踪 skynet 服务间的消息请求及性能分析" »

May 22, 2018

Ericsson Texture 压缩贴图 EAC 的编码器

最近在做新引擎 UI 模块的工作。汉字字体纹理需要占比较大的一张贴图,考虑到这张贴图只需要用一个通道就够了,所以我决定使用压缩贴图。在手机设备上,GL_COMPRESSED_R11_EAC 是一个不错的选择。

EAC 是 Ericsson 提出的对单通道贴图的压缩方案,现已进入 OpenGL 的官方标准。它通常会结合 ETC2 一起使用。ETC2 负责 RGB 部分,EAC 负责 Alpha 通道。偶尔也可以单独使用。它会将每个像素解码为 [0,2047] 的整数,有 11bits 的精度,故而被称为 R11_EAC 。不过,我阅读文档后发现,其实有效精度是 8 bits ,一般也是从 8bits 的原始数据中编码得到的。压缩后,每 4 * 4 = 16 个像素会被编码为 64 bits ,压缩比 2 : 1 。用于字体纹理的话,可以节省一半的显存空间。

阅读全文 "Ericsson Texture 压缩贴图 EAC 的编码器" »

May 08, 2018

断点单步跟踪是一种低效的调试方法

断点单步跟踪的交互式调试器是软件开发史上的一项重大发明。但我认为,它和图形交互界面一样,都是用牺牲效率来降低学习门槛。本质上是一种极其低效的调试方法。

我在年少的时候( 2005 年以前的十多年开发经历)都极度依赖这类调试器,从 Turbo C 到 Visual C++ ,各个版本都仔细用过。任何工具用上十年后熟能生巧是很自然的事。我认为自己已经可以随心所欲用这类工具高效的定位出 bug 了。但在 2005 年之后转向跨平台开发后,或许是因为一开始没能找到 Linux 平台上合适的图形工具,我有了一些时间反思调试方法的问题。GDB 固然强大,但当时的图形交互外壳并不像今天的版本这么完善。当时比较主流的 insight ddd 都有些小问题,用起来不是十分顺手。我开始转换自己平时做开发的方式。除了尽量提高自己的代码质量:写简洁的、明显没有问题的代码之外,多采用不断的代码复核(Code Review),有意识地增加日志输出,来定位 Bug 。

后来开发重心从客户端图形开发逐步转向服务器,更加显露出用调试器中断程序运行的劣势来。对于 C/S 结构的软件,中断一边的代码运行,用人的交互频率单步跟踪运行,而另一边是以机器的交互频率运作,像让软件运行流程保持正常是非常困难的。

这些年的工作中又慢慢加入一些 Windows 下的开发工作。我发现经过了再一个十年的训练,即使偶尔用上交互式调试器,也体会不到什么优势了。往往手指按在跟踪调试按键上机械的操作,脑子里想的却不是眼前看到的屏幕上的代码。往往都没执行到触发 Bug 的位置,已经恍然大悟发现写错的地方了。这种事情多了,自然会对过去的方法质疑,是什么导致了调试器的低效。

阅读全文 "断点单步跟踪是一种低效的调试方法" »

Misc

Categories

Archives

Recent Comments