flagship的理想与现实
创新+实践
C++博客
::
首页
::
联系
::
聚合
::
管理
8 Posts :: 0 Stories :: 27 Comments :: 0 Trackbacks
常用链接
我的随笔
我的评论
我参与的随笔
留言簿
(8)
给我留言
查看公开留言
查看私人留言
我参与的团队
随笔分类
FlagshipEngine(8)
其他
游戏编程
游戏设计
随笔档案
2009年3月 (2)
2009年2月 (1)
2009年1月 (5)
搜索
最新评论
1. re: 几种多线程3D引擎架构的比较
sx
--psychehao
2. Unreal游戏引擎3教学中文字幕
评论内容较长,点击标题查看
--Unreal游戏引擎
3. re: 几种多线程3D引擎架构的比较
不错
--Giser
4. re: 多Pass渲染体系与多线程渲染的矛盾
OGRE里已经把dx9和dx10API抽象了,楼主可以了解一下。
另,楼主有没有考虑过如果加上网络下载线程时多线程的设计?
--Combine
5. re: 几种多线程3D引擎架构的比较
哥们你这个思想 和我做的游戏 一样 我们游戏项目 也是这个思想
QQ 23505105
--geforce
阅读排行榜
1. 几种多线程3D引擎架构的比较(6817)
2. 3D引擎多线程:渲染与逻辑分离(5492)
3. 3D引擎多线程:资源异步加载(3510)
4. DX11与多线程渲染(3298)
5. 3D引擎多线程:框架(2834)
评论排行榜
1. 几种多线程3D引擎架构的比较(10)
2. 3D引擎多线程:渲染与逻辑分离(7)
3. DX11与多线程渲染(4)
4. 多Pass渲染体系与多线程渲染的矛盾(3)
5. 3D引擎多线程:框架(1)
3D引擎多线程:渲染与逻辑分离
目前的3D引擎的渲染帧和逻辑帧都是在一个线程上运行的,在网络游戏中大量玩家聚集,繁重的骨骼动画计算和粒子计算极大的拖累了渲染帧数,有两种有效措施:1、控制同屏显示人数,但玩家体验不好 2、帧数低于某值时减少动画Tick频率,但带来的问题是动画不连贯。
如果考虑使用多线程优化,最容易想到的就是采用平行分解模式,将骨骼动画计算和粒子计算写成两个for循环,然后用OpenMP将其多线程化,但事实上这样并不会提高多少效率,这两者计算仍然要阻滞渲染帧,线程的创建也有一定的消耗。于是我想到了一种极端的解决方案,采用任务分解模式,将渲染和逻辑完全分离到两个线程去,互不影响,当然这样线程同步会是大问题,毕竟线程的数量和BUG的数量是成正比的。
我们首先来分析下这两个线程分别需要做什么工作,需要那些数据。渲染线程需要获取实体的位置、材质等信息,并交给GPU渲染,逻辑线程需要更新实体的位置、材质、骨骼动画等数据,很显然一个写入一个读取,这为我们实现一个没有线程同步的多线程3D渲染系统提供了可能。
为了让读取和写入不需要Lock,我们需要为每一份数据设计一个带有冗余缓存的结构,读取线程读取的是上次写入完成的副本,而写入线程则向新的副本写入数据,并在完成后置上最新标记,置标记的操作为原子操作即可。以Vector为例,这个结构大致是这样的:
struct
VectorData
{
Vector4f m_pVector[DATACENTER_CACHE];
int
m_iIndex;
VectorData()
{
memset( m_pVector,
0
, DATACENTER_CACHE
*
sizeof
(Vector4f) );
m_iIndex
=
0
;
}
void
Write( Vector4f
&
rVector )
{
int
iNewIndex
=
m_iIndex
==
DATACENTER_CACHE
-
1
?
0
: m_iIndex
+
1
;
m_pVector[iNewIndex]
=
rVector;
m_iIndex
=
iNewIndex;
}
Vector4f
&
Read()
{
return
m_pVector[m_iIndex];
}
}
;
当然我们可以用模板来写这个结构,让其适用于int,float,matrix等多种数据类型,余下的工作就简单了,将所有有共享数据的类的成员变量都定义为以上这种数据类型,例如我们可以定义:
SharedData<Matrix4f> m_matWorld;
在渲染线程中调用pDevice->SetWorldMatrix( m_matWorld.Read() );
在逻辑线程中调用m_matWorld.Write( matNewWorld );
需要注意的是,这种方案并非绝对健壮,当渲染线程极慢且逻辑线程极快的情况下,有可能写入了超过了DATACENTER_CACHE次,而读取却尚未完成,那么数据就乱套了,当然真要出现了这种情况,游戏早已经是没法玩了,我测试的结果是渲染帧小于1帧,逻辑帧大于10000帧,尚未出现问题。
FlagshipEngine采用了这一设想,实际Demo测试结果是,计算25个角色的骨骼动画,从静止到开始奔跑,单线程的情况下,帧数下降了20%~30%,而使用多线程的情况下,帧数完全没有变化!
posted on 2009-01-04 21:15
flagship
阅读(5492)
评论(7)
编辑
收藏
引用
所属分类:
FlagshipEngine
Feedback
#
re: 3D引擎多线程:渲染与逻辑分离
2009-01-05 09:20
LOGOS
yf同学吧。使劲的踩一下,oye,处女踩
我看过的一个同步方案,和你的不同
逻辑线程在每帧结束的时候,将新的渲染context同步到渲染线程中
渲染线程在没有新的context的仍用老的context渲染
你使用了过于底层的数据结构作为数据的同步方案,看起来以后的拓展性不是太好。
另外,jl同学说了,m_index=index在intel的CPU上也许是原子操作,但是其他CPU就不一定了。所以read方法读取到的是不是一个合法的索引值很难说
回复
更多评论
#
re: 3D引擎多线程:渲染与逻辑分离
2009-01-05 10:41
flagship
啊!被发现了。。hwh同学。。你也在这里啊
你看过的同步方案,给我个链接吧
安全性的问题,我查过,在32位x86 CPU上int的赋值应该是原子操作,不过考虑保险,想试着改成InterlockedIncrement试试看,不知道会不会损失效率
@LOGOS
回复
更多评论
#
re: 3D引擎多线程:渲染与逻辑分离
2009-01-05 11:08
LOGOS
http://www.cnblogs.com/cproom/archive/2007/11/26/972548.html
回复
更多评论
#
re: 3D引擎多线程:渲染与逻辑分离
2009-01-16 11:06
落魄江湖-随风而行
第一次尝试评论,先测试一下
回复
更多评论
#
re: 3D引擎多线程:渲染与逻辑分离
2009-01-16 11:22
落魄江湖-随风而行
关于多线程(或smp)渲染,是一个比较麻烦的手段,通过doom3 sdk结合quake3源代码,我这里也总结一下DOOM3/QUAKE3的多线程(SMP)渲染技术框架,供参考。
首先定义逻辑,逻辑端不涉及任何渲染操作和资源载入,仅仅是各个ENTITY的动态变化和物理碰撞检测等,可以形成一套脚本语言,分配一个线程,称为脚本线程,专门从事业务逻辑处理,逻辑代码由逻辑程序员编写。
其次,定义渲染,渲染分为两个线程,即渲染前端线程和渲染后端线程
渲染前端线程的主要作用是进行场景管理,可视性检测,形成COMMAND BUFFFER命令,在渲染前端线程里面不涉及到任何的渲染API的调用,例如GL/D3D等,然后由渲染前端将可视化的渲染数据提交给渲染后端,渲染后端从COMMANDBUFFER中获得渲染数据后,进行BATCH,设置渲染状态等,提交给渲染API进入GPU硬件流水线
使用COMMAND BUFFER事实上已经成为并行渲染系统的标准解决方案了,D3D FOR XBOX版本的API函数里面包含COMMAND BUFFER接口,事实上QUAKE3是第一个引擎使用COMMAND BUFFER实现SMP渲染的引擎。
随风而行 QQ群 38224573 3D引擎研发[1]
回复
更多评论
#
re: 3D引擎多线程:渲染与逻辑分离
2009-01-16 16:06
flagship
@落魄江湖-随风而行
COMMAND BUFFER 我不太了解,这就去查一下
我想问的是:逻辑线程如何与渲染前端线程同步的?
回复
更多评论
#
re: 3D引擎多线程:渲染与逻辑分离
2009-02-05 16:21
conan
这个就是和ringbuffer差不多
回复
更多评论
刷新评论列表
只有注册用户
登录
后才能发表评论。
【推荐】100%开源!大型工业跨平台软件C++源码提供,建模,组态!
相关文章:
几种多线程3D引擎架构的比较
多Pass渲染体系与多线程渲染的矛盾
DX11与多线程渲染
3D引擎多线程:逻辑操作
3D引擎多线程:框架
3D引擎多线程:渲染与逻辑分离
3D引擎多线程:资源异步加载
开篇:关于FlagshipEngine
网站导航:
博客园
IT新闻
BlogJava
知识库
博问
管理
Copyright @ flagship
Powered by:
.Text
and
ASP.NET
Theme by:
.NET Monster