游戏引擎基于Handle的资源管理
基于Handle的资源管理方案,第一时间想到的应该是Windows了,但是真正想让我实施这个方案的,是《游戏编程精粹1》里面的游戏资源管理篇章的给出的方案。在《游戏编程精粹1》里面的资源标示Handle类,是一个极为简单的32位int类型,分为前16位的index和后16位的magic num,magic num主要是用来用作资源的校验的,在获取实例资源和删除实例资源的时候,都会校验一次。这两个数据合成一个int32用来标示唯一的资源。
union
{
enum
{
MAX_BITS_INDEX = ,
MAX_BITS_MAGIC = , MAX_INDEX = ( << MAX_BITS_INDEX) - ,
MAX_MAGIC = ( << MAX_BITS_MAGIC) - ,
}; struct
{
unsigned mIndex : MAX_BITS_INDEX;
unsigned mMagic : MAX_BITS_MAGIC;
}; uint mHandle;
};
当然,这个Handle在书里面是定义成模板了,主要还是转为C++的习惯,变成一种强类型的标示吧,不同资源类型不能相互赋值和转化。
接来下是定义HandleManager,这个类也是一个模板,就跟名字一样,是用来管理Handle的,里面有两个vector,一个是保存正在使用的资源的vector,一个是删除资源后放入的free vector,当用户需要新建一个Handle的时候,会优先从free vector里面查找空的Handle,重新指向新的资源。
但是这个Handle的指向资源实例数组的index是不会变的,会变的只是magic num。总的来说,Handle还是变了。
template<typename DATA, typename RESHANDLE>
DATA * ResHandleMgr<DATA, RESHANDLE>::acquire(RESHANDLE &handle)
{
uint index;
if (mFreeSlots.empty())
{
index = mMagicNums.size();
handle.init(index);
DATA *pData = new DATA();
mUserVec.push_back(pData);
mMagicNums.push_back(handle.getMagic());
}
else
{
index = mFreeSlots.back();
// init后,magic num 会加一
handle.init(index);
mFreeSlots.pop_back();
mMagicNums[index] = handle.getMagic();
} //return (mUserVec.begin() + index);
UserVec::iterator iter = mUserVec.begin() + index;
return *iter;
}
这个大体就是《游戏编程精粹1》里面的引擎资源管理方案了,要保存资源很简单,持有Handle就行了,要获取和删除资源直接用Handle就行了。但是,估计大家也看来出什么问题了,资源没有自动释放的机制!!!!!!!
于是,我在Handle类里面加了个变量,用来作为引用计数,这里暂时没有引入智能指针(这个引用计数优化的方法应该可以加入一个内存池)
private:
union
{
enum
{
MAX_BITS_INDEX = ,
MAX_BITS_MAGIC = , MAX_INDEX = ( << MAX_BITS_INDEX) - ,
MAX_MAGIC = ( << MAX_BITS_MAGIC) - ,
}; struct
{
unsigned mIndex : MAX_BITS_INDEX;
unsigned mMagic : MAX_BITS_MAGIC;
}; uint mHandle;
};
//保存引用计数
uint *mpRefCount;
在Handle释放的时候,handle.release(),在Handle赋值的时候,handle.addRef,当(*mpRefCount) == 0的时候,就可以释放资源资源了。
一开始的时候,将引用计数设置为static std::map<int, int>(前面一个int表示Handle,后面一个表示引用次数),后来发现效率实在太低,于是改为 uint *mpRefCount指针这种形式,帧数上升了20 FPS左右。。。
这个Handle类大体长这个样子的,基本也可以实现资源的自动释放机制了
template<typename ResType>
class ENGINE_DLL ResHandle
{
public:
ResHandle();
ResHandle(const ResHandle &handle); ~ResHandle(); void init(uint index);
uint getIndex() const;
uint getMagic() const;
uint getHandle() const; bool isNull() const; operator uint() const; void addRef(); void release(); ResHandle &operator =(ResHandle handle)
{
mHandle = handle.getHandle();
if (handle.isNull() == false)
{
assert(handle.mpRefCount != );
if (isNull() == false && mpRefCount)
{
release();
if (mpRefCount != )
assert(mpRefCount == handle.mpRefCount);
}
}
mpRefCount = handle.mpRefCount;
addRef();
return *this;
} private:
union
{
enum
{
MAX_BITS_INDEX = ,
MAX_BITS_MAGIC = , MAX_INDEX = ( << MAX_BITS_INDEX) - ,
MAX_MAGIC = ( << MAX_BITS_MAGIC) - ,
}; struct
{
unsigned mIndex : MAX_BITS_INDEX;
unsigned mMagic : MAX_BITS_MAGIC;
}; uint mHandle;
}; uint *mpRefCount;
}; template<typename ResType>
ResHandle<ResType>::ResHandle(const ResHandle &handle) :
mpRefCount()
{
mHandle = handle.getHandle();
mpRefCount = handle.mpRefCount;
addRef();
} template<typename ResType>
ResHandle<ResType>::~ResHandle()
{
release();
} template<typename ResType>
void ResHandle<ResType>::release()
{
if (mHandle != )
{
--(*mpRefCount);
if (*mpRefCount == )
{
//std::cout << "need delete !!!!" << std::endl;
//delete operator
//后面加入
Log::getInstancePtr()->logMsg("release res handle = %d", mHandle); SAFE_DELETE(mpRefCount);
}
}
} template<typename ResType>
void ResHandle<ResType>::addRef()
{
if (mHandle != )
{
++(*mpRefCount);
}
} template<typename ResType>
ResHandle<ResType>::ResHandle() :
mHandle(),
mpRefCount()
{ } template<typename ResType>
void ResHandle<ResType>::init(uint index)
{
assert(isNull());
assert(index <= MAX_INDEX); static uint sAutoMagic = ; if (++sAutoMagic > MAX_MAGIC)
{
sAutoMagic = ;
} mIndex = index;
mMagic = sAutoMagic; if (mpRefCount == )
{
mpRefCount = new uint;
}
*mpRefCount = ;
} template<typename ResType>
ResHandle<ResType>::operator uint() const
{
return mHandle;
} template<typename ResType>
bool ResHandle<ResType>::isNull() const
{
return !mHandle;
} template<typename ResType>
uint ResHandle<ResType>::getHandle() const
{
return mHandle;
} template<typename ResType>
uint ResHandle<ResType>::getMagic() const
{
return mMagic;
} template<typename ResType>
uint ResHandle<ResType>::getIndex() const
{
return mIndex;
} //------------------------------------------------------------------- template < typename Tag>
inline bool operator != (ResHandle<Tag> l, ResHandle<Tag> r)
{
return (l.getHandle() != r.getHandle());
} template < typename Tag>
inline bool operator == (ResHandle<Tag> l, ResHandle<Tag> r)
{
return (l.getHandle() == r.getHandle());
}
游戏引擎基于Handle的资源管理的更多相关文章
- 转:高层游戏引擎——基于OGRE所实现的高层游戏引擎框架
高层游戏引擎——基于OGRE所实现的高层游戏引擎框架 这是意念自己的毕业论文,在一个具体的实践之中,意念主要负责的是物件和GUI之外的其他游戏系统.意念才学疏陋,望众位前辈不吝赐教.由于代码质量不高. ...
- 游戏引擎架构 (Jason Gregory 著)
第一部分 基础 第1章 导论 (已看) 第2章 专业工具 (已看) 第3章 游戏软件工程基础 (已看) 第4章 游戏所需的三维数学 (已看) 第二部分 低阶引擎系统 第5章 游戏支持系统 (已看) 第 ...
- 对HGE游戏引擎的一次封装
HGE游戏引擎是一个开源2D游戏引擎,基于directX. 它的渲染及逻辑是基于帧回调的框架模式, 其提供一些主要的图像操作和输入控制功能. 我在之前写一个2D游戏的时候对它整个框架进行了一次封装,非 ...
- Android游戏引擎总汇 原文出处:http://software.intel.com/en-us/blogs/2012/03/13/game-engines-for-android?page=1
随着Android系统的使用越来越广泛,了解一下Android平台下的游戏引擎就非常有必要.而同时因为基于Intel x86的移动设备越来越多,我也非常关注支持x86的移动游戏引擎.然而就目前为止游戏 ...
- Atitit 基于dom的游戏引擎
Atitit 基于dom的游戏引擎 1. 添加sprite控件(cocos,createjs,dom)1 1.1.1. Cocos1 1.1.2. createjs1 1.1.3. Dom模式2 1. ...
- 浅析游戏引擎的资源管理机制——扒一扒Unity3D中隐藏在背后的资源管理
游戏中通常有大量资源,如网格.材质.纹理.动画.着色器程序和音乐等,游戏引擎作为做游戏的工具,自然要提供良好的资源管理,让游戏开发者用最简单的方式使用资源.游戏引擎的资源管理包括两大部分:离线资源管理 ...
- 推荐一款基于XNA的开源游戏引擎《Engine Nine》
一.前沿导读 XNA是微软基于.Net部署的下一代3D/2D游戏开发框架,其实XNA严格来说类似下一代的DirectX,当然不是说XNA会取代DirectX,但是基于XNA我们对于面向XBOX360, ...
- 基于Java的开源3D游戏引擎jMonkeyEngine
jMonkeyEngine简介 jMonkeyEngine是一款纯Java语言编写的游戏引擎,继承了Java应用跨平台的特性,而且是开放源代码的,遵循BSD开源协议,BSD开源协议用一句简单的话概括就 ...
- 开源免费的HTML5游戏引擎
青瓷引擎的成长 青瓷引擎自2015年4月项目启动开始,7月首次亮相2015年ChinaJoy,便得到业界的极大关注,随后开启限量测试,收到数百个开发者团队的试用申请及反馈,期间经历了18个内测版本,完 ...
随机推荐
- 字符集研究之多字节字符集和unicode字符集
作者:朱金灿 来源:http://blog.csdn.net/clever101 本文简介计算机中两大字符集:多字节字符集和unicode字符集的出现及关系. 首先我们须要明确的是计算机是怎样找到字符 ...
- 远程桌面连接centos 7
首先安装tigervnc-server: yum install tigervnc-server 安装好后,设置 vi /etc/sysconfig/vncservers [root@gateway- ...
- 【C语言天天练(十一)】深入理解指针
引言:在C语言中.指针的地位是不言而喻的,要想非常好的掌握C语言,掌握指针是必须的,这也是C语言不同于其它语言的地方. (一)指针的指针 样例: int i; int *pi;/*把pi初始化为指向变 ...
- 【Python】读取cvs文件报错:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb1 in position 6: invalid start byte
现在有文件data.csv 文件编码格式为:ANSI data.csv 1|1|1|北京市 2|1|2|天津市 3|1|3|上海市 4|1|4|重庆市 5|1|5|石家庄市 6|2|5|唐山市 7|3 ...
- 利用动态图添加Loading动画
opacity:CSS3中的属性,调节透明度,一般取值0.5 添加思想: 1.对超链接添加点击事件,通过new {@onclick="showLoading()"} Html.Ac ...
- Gson把对象转成json格式的字符串
近期在做一个java web service项目,须要用到jason,本人对java不是特别精通,于是開始搜索一些java平台的json类库. 发现了google的gson.由于之前对于protoco ...
- c#中Monitor的使用
首先lock和Minitor有什么区别呢? 其实lock在IL代码中会被翻译成Monitor.也就是Monitor.Enter(obj)和Monitor.Exit(obj). lock(obj) { ...
- 关于ejabberd限制单点登录
ejabberd 是对xmpp协议的完全实现,那么单纯的ejabberd是不提供该功能限制的,但是从我们的xmpp协议则可以完全的解决这个问题,我们通过jid对它进行限制,下面可以看一下jid的解释: ...
- ASP.NET动态网站制作(6)-- JS(1)
前言:JS的第一节课,在Visual Studio 2013中编写及运行.新建项目->Web->ASP.NET Web应用程序->Empty,打开后在项目下添加新建css文件夹和js ...
- 【BZOJ3745】[Coci2015]Norma cdq分治
[BZOJ3745][Coci2015]Norma Description Input 第1行,一个整数N: 第2~n+1行,每行一个整数表示序列a. Output 输出答案对10^9取模后的结果. ...