我是一个很懒的bloger,总想着有时间写blog,还不如多写几行代码。但仔细想想,代码是永远写不完的,而blog却不想就此荒废。所以在敷衍公司的年终总结之前,还是坐下来真正地总结一下自己在过去一年中的得失吧。
Fancystar开动
从上海回来后的空档期,研究了很多关于多线程方面的内容,再加上之前Gamebryo的经验,结果是脑袋里各种新的想法开始涌动。于是想要对老SDK进行改造。老SDK大部分是对老余GameBox的模仿,传统的单线程客户端,渲染也只运用到OpenGL 1.x的水平。最终我决定重写这3W多行的客户端代码,采用新的渲染架构,并且可以运用更多的CPU。这就是Fancystar。
多线程和Lock-Free
这是一个严重杀伤脑细胞的领域,在跌跌撞撞摸爬打滚了几个月之后,才终于悟到了一点门道。本来也酝酿过几篇文章想要总结一下这方面的心得,由于各种原因却一直未有成文。
Fancystar的第一个尝试,就是采用多线程架构,以利用更多的CPU核心。这通常有两种选择(其实还有第3种,即1和2的混合):
- 将子系统拆分到不同的线程中并行执行
- 采用任务(task)/ 调度器(scheduler)/ 工作线程(worker)模型
开始的时候Fancystar选择了1,试图将输入,逻辑,渲染,物理等各个子系统拆分到不同的线程中并行执行。这会遭遇几个问题:
首先每个object的数据同样要拆分为N个部分,分别由不同的子系统来管理,相当于每个object在不同的子系统中都有proxy(称为代理,或分身)。这些proxy相互之间独立性越强越好,但无论怎样设计,通信总是无法避免的。通信方式要么是传引用,要么是值拷贝。传引用的话,是类似于流水线的方式:proxy1更新数据—>通知proxy2数据更新完毕—>proxy2获得指针并执行自己的操作。在proxy1通知proxy2之后,proxy1(在下一帧之前)就不再允许修改共享数据了,否则就要涉及到线程同步的问题。在实际游戏逻辑中,这条规则是难以维护的。于是很自然就会想到用值拷贝。类似于double buffer (甚至triple buffer),共享数据同时存在多份拷贝,每个proxy独占一份,只在关键点同步一次。这种方法内存占用几乎翻倍,但更安全更容易维护。尽管如此,由于总想着尽量减少同步的次数和数据量,自然就会引入复杂的状态系统,以跟踪每份共享数据的变化。以上2种实现Fancystar都曾尝试使用过,但在写了一些简单的DEMO后就放弃了,因为设计出来的系统实在很难使用。
其次,这种按子系统进行拆分的方式是不利于扩展的。对于游戏来说,子系统的数量是有限的。即使在最优配置的状况下,也只能每个系统分配一个core,更多的core将会被浪费掉。此外,不同的子系统,其负载是极度不相称的。物理系统需要大量的运算,而输入和声音则想到休闲。所以最终整个系统会被最慢的那个子系统所拖累,而最慢的子系统却无法获得更多的运算时间(即使有),与此同时某些子系统所在的core却在idle。
所以最后Fancystar选择了2:整个系统还是在同一个线程中运行,但可以将运算封装成task,由scheduler进行调度,分配到不同的worker thread中去执行。core越多,worker thread就越多。采用这种方式,则主逻辑中无需考虑线程同步的问题,只要在几个热点处将运算分包出去并等待结果就可以了。Gamebryo就是采用这样的方法(虽然早已看过文档,但直到后来才意识到这种设计的优点)。在某篇介绍Capcom新引擎的论文中也提到了类似的技术(但更加彻底,复杂),并用在了 Lost Planet 和 Dead Rising 中。
尽管走了很多弯路,但总算具备了雏形。工作成果包括:线程工具库,提供atomic操作,hazard pointer,各种lock-free队列,lock-free对象池等;重新修改了object系统,提供线程安全的引用计数和回收机制,并全面采用component模式;实现 task / scheduler / worker机制;重写了异步资源管理系统;客户端框架在历经多次修改后也基本确定了下来。
OpenGL3和GLSL
对于本人来说,去年另外一个最重要的进步就是,我开始了GPU编程的旅程。从零开始设计渲染模块,在CPU和GPU间切换,写shader程序,这些都是全新的体验,感觉非常美妙。 Fancystar完全抛弃了老SDK的渲染代码,用OpenGL3 core profile 和 GLSL shader来重写。研究渲染技术,将会是今年的工作重点。
(左) 纪念第一个shader程式 (右) 用shader实现的tile map
游戏
去年主要参与了两个项目,一个是业余时间开发的bombman,以插件的形式将Fancystar跑在浏览器上面,游戏可以native client和web两种形式运行。该项目最后无疾而终了,业余团队在凝聚力上还是有很大的问题。另一个就是工作室的angel,是个很愉快的项目,我的主要工作集中在编辑器和AI上面,下个月就杀青了,敬请期待,呵呵。
读书
在Kindle上速读了一遍 OpenGL Super Bible 5th,整体上对OpenGL3和GLSL有了一定的了解。第5版完全抛弃了老旧的API,从core profile和shader开始阐述新的OpenGL架构,这应该是最好的OpenGL的入门书了吧。第二本读的是 Texturing & Modeling,讲程序纹理和建模技术的。在读了前面几章之后,决定系统地学习现代计算机图形学,于是转而去读 Real-Time Rendering。这是一本超棒的书,作者站在很高的位置来阐述问题,经常给我带来“哦,原来如此”的感觉。第4章之后的内容对我来说逐渐变得艰深起来,往往需要根据书中提供的reference阅读更多的扩展资料才能理解书中所阐述的问题。争取今年能把此书读完,并将其中的理论和技术应用到Fancystar中。
此外我还读了大量关于并发编程,内存模型,以及Lock-Free算法的论文,有时间的话会将这些资料整理出来跟大家分享。
最后
在2011岁末获得可爱LOLI一只,感谢上苍!

0 Responses
Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.