目前的3D引擎的渲染帧和逻辑帧都是在一个线程上运行的,在网络游戏中大量玩家聚集,繁重的骨骼动画计算和粒子计算极大的拖累了渲染帧数,最终采取了亮点措施:1、控制同屏显示人数,但玩家体验不好 2、帧数低于某值是减少动画Tick频率,但带来的问题是动画不连贯。
如果考虑使用多线程优化,最容易想到的就是将骨骼动画计算和粒子计算写成两个for循环,然后用OpenMP将其多线程化,但事实上这样并不会提高多少效率,这两者计算仍然要阻滞渲染帧。于是我想到了一种极端的解决方案,将渲染和逻辑完全分离到两个线程去,互不影响,当然这样线程同步会是大问题,毕竟线程的数量和BUG的数量是成正比的。
我们首先来分析下这两个线程分别需要做什么工作,需要那些数据,渲染线程需要获取实体的位置、材质等信息,并交给GPU渲染,逻辑线程需要更新实体的位置、材质、骨骼动画等数据,很显然一个写入一个读取,这为我们实现一个没有线程同步的多线程3D渲染系统提供了可能。
为了让读取和写入不需要Lock,我们需要为没一份数据设计一个类似循环链表的结构,读取线程读取的是上次写入完成的副本,而写入线程则向新的副本写入数据,并在完成后置上最新标记,以Vector为例,这个结构大致是这样的:
struct VectorData
{
Vector4f m_pVector[DATACENTER_CACHE];