读书人

Cocos2d-x 3.0 新的点染架构

发布时间: 2013-10-12 11:54:04 作者: rapoo

Cocos2d-x 3.0 新的渲染架构

?

?在单线程架构中,游戏逻辑和渲染操作是顺序执行的。两者消耗的时间加起来如果超过 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 -

读书人网 >操作系统

热点推荐