8月1号这一天,cocos2d-x 官方微博上说 x 团队正在纠结是否用智能指针替换现有的引用计数内存管理机制,结果引发大家的争论。
在我看来,引发这个争论的原因是 cocos2d-x 打算实现多线程化,从而充分利用现代智能手机的多核处理器资源。而多线程化的一个最重大需求,应该就是 cocos2d-x 3.0 新的渲染架构了。
cocos2d-x 3.0 的渲染架构设计来自 Zynga(原始设计文档)。在这个架构设计中,游戏将分为两个主要的线程:main thread 和 draw thread。
main thread 运行游戏的逻辑代码,例如在场景的 update() 函数中改变角色位置、在 schedule selector 函数中创建新敌人等等。
main thread 中的代码会改变 Scene 中的 Node Tree,但并不实际执行 OpenGL 渲染操作。作为替代,main thread 将绘图操作转换为一系列的 draw command,发送到一个 queue 中。
draw thread 则在每一帧绘制前,从 queue 里提取 draw command,然后进行优化,再转换为实际的 OpenGL 渲染操作。
在单线程架构中,游戏逻辑和渲染操作是顺序执行的。两者消耗的时间加起来如果超过 1/60 秒,就会导致游戏出现卡顿现象。
分成多线程后,main thread 有更多的时间来执行游戏逻辑。而 draw thread 也有更多的时间做优化和渲染操作,例如实现 automatic batching。
新渲染架构可能的实现方案
Zynga 的设计文档并没有给出细节实现原理,我就以大家讨论的内容整理了一个可能的方案。
main thread 会每 1/60 秒的频率调用 Scene::drawScene() 方法。这个方法有如下步骤:
发送一个 begin command 到一个 command queue
update() 执行所有的 schedule selector 和 event listener,游戏逻辑大部分就在其中。
扫描整个 Node Tree,构造一系列 draw command,并发送到 queue
发送一个 end command 到 queue,形成一个完整的 commands list
如果某次 drawScene() 消耗的时间超过 1/60 秒,则无需等待,立即开始下一次 drawScene() 调用。这样确保游戏的逻辑能够以最高 60fps 运行,但又不会超过 60fps。
draw thread 按照如下步骤以最快 1/60 秒的频率执行:
从 queue 中找出最后一组 list(如果 draw thread 每次绘图消耗时间超过 1/60 秒,queue 中就可能包含多组 list,放弃之前的 list 可以确保画面符合最近的游戏状态)。
对 list 进行处理,执行画面渲染。
更新 queue,删除已绘制的 list 及其之前的所有 list。
Texture 对象不再保存材质的实际数据,改为保存一个 texture id。材质的实际数据由 draw thread 进行管理。
当加载一个材质文件时,main thread 中构造一个新的 Texture 对象,并获得一个新的 texture id。然后发送 load texture command,并将材质文件名和 texture id 作为 command 的参数传递给 draw thread。draw thread 可以在自己线程里载入材质数据,或新开线程载入数据。
当一个 Texture 被 Sprite 使用时,增加 Texture 对象的引用计数。而使用该 Texture 的 Sprite 删除时,则减小引用计数。如果 TextureCache 需要释放不再引用计数为 0 的 Texture 对象,就发送 release texture command。
在 cocos2d-x 2.x 版中,CCNode 包含了位置、大小、缩放、旋转等信息,以及 OpenGL 绘图需要的数据。
在新架构里,main thread 维护的 Node Tree 中,Node 不再包含 OpenGL 绘图需要的数据。而是在构造 Node、改变 Node 状态时,才将 Node 的状态数据发送给 draw thread。
draw thread 根据 node id 维护 node 的绘图数据。
如果 main thread 执行后,Node 的状态没有发生改变,就无需发送该 Node 的 draw command,也就避免了 draw thread 对没有发生变化的 Node 重新计算绘图数据。
cocos2d-x 3.0 必须要实现线程安全?
在整个设计里,main thread 不停的往 command queue 追加数据,而 draw thread 每完成一次画面渲染就清理一次 command queue。因此 queue 的实现必须是线程安全的,主要的操作都应该满足原子性要求。
但从这个设计看,只要保证两点,那么 main thread 里的对象是不是线程安全根本无所谓:
queue 是线程安全的
draw thread 不使用自动释放的引用计数对象
所以这样一番分析后,感觉 cocos2d-x 3.0 要多线程化,就不一定要做大改动。
但实际上 cocos2d-x 3.0 里还需要多线程完成异步 IO(例如网络)、异步计算等等。而且提供一个可靠的线程安全架构,也方便开发者创建线程来优化游戏体验(比如把 AI 算法放入单独的线程)。
所以从整体架构上看,cocos2d-x 3.0 实现线程安全还是很有必要的。但实现线程安全是否就一定要用智能指针吗?这个我会另外写一篇文章来探讨此问题。
最后,欢迎大家多多提意见。
- END -
相关推荐
cocos2d-x 3.0 人物行走 . 包里有代码和 图片资源.
这是我重新弄的cocos2d-x-3.0的类图.之前别人兄台弄的,有些不全面,有些地方错误.我这个可以说是最新的了.每个类添加了中文的详细注解,同时也添加了中文的类名称翻译.这样对cocos2d-x-3.0的框架比较好上手. 有兴趣的...
Cocos2d-x3.0正式版 练练看 源码。有注释。
这是cocos2d-x 3.0 类关系图, 这个制作者是:gamecocos2dx 他做的Xmind,我导出的PNG格式,我推荐还是看Xmind,里面还有一些注释 gamecocos2dx Xmind下载地址:...
兄弟连cocos2d-x3.0 final视频教程 1.Cocos2d-x手机游戏开发C编程基础 2.Cocos2d-x手机游戏开发C++编程基础 3.Cocos2d-x3.0 final手机游戏开发核心技术 4.实例:贪吃蛇 5.实例:微信飞机大战
这是一个cocos2d-x 3.0中文开发文档.
http://blog.csdn.net/zoyzn/article/details/27251633一文的源码。cocos2d-x 3.0导出自定义类到lua,并导出自定义类的名称空间到lua。
cocos2d-x 3.0 骨骼动画 demo 以及注意事项
本游戏基于cocos2d-x 3.0版本,可能不适用于cocos2d-x 2.x版本,请看清楚,再参考! 使用方法:将Classes中的类全部拷贝到新建cocos项目的Classes项目中,将Resources下的所有文件拷贝到对应的文件下,运行即可!
资源名称:Cocos2d-x实战:JS卷——Cocos2d-JS开发内容简介:本书是介绍Cocos2d-x游戏编程和开发技术书籍,介绍了使用Cocos2d-JS中核心类、瓦片地图、物理引擎、音乐音效、数据持久化、网络通信、性能优化、多平台...
官网中文docs文档的例子下载 创建工程的时候一定要创建一样的文件名 http://www.cocos2d-x.org/docs/tutorial/framework/native/how-to-drag-and-drop-sprites/zh
cocos2d-x 3.0 rapidjson 读取Json
Cocos2d-x3.0final 自学教程的配套代码http://blog.csdn.net/column/details/cocos2dx2014.html
Cocos2d-x3.0游戏实例《别救我》源码。 教程地址:http://blog.csdn.net/musicvs/article/details/24928929
cocos2d-x 3.0 开发文档英文版(html)
Cocos2d-x 3.0 过渡学习 尊重原创,转载来自:star特530的CSDN博客 :http://blog.csdn.net/star530?viewmode=contents
cocos2d-x 3.0-alpha0 SDK头文件和DLL文件
Cocos2d-x 3.0 开发(九)使用Physicals代替Box2D和chipmunk的3.0 alpha1新版本 对应于Coco2d-x 3.0 alpha1 使用,更新之前3.0 alpha0 的 文件。相关博客地址:...
cocos2d-x3.0+cocostudio1.4,适合初学,冒险过关游戏
这个原本是老G开发的一个动画工具,移植到cocos2d-x3.0而已