3D引擎多线程:资源异步加载

本文原创版权归 博客园 flagship 所有,如有转载,请详细标明作者及原文出处,以示尊重!

作者:flagship

原文:3D引擎多线程:资源异步加载

        资源异步加载恐怕是3D引擎中应用最为广泛的多线程技术了,特别是在无缝地图的网络游戏中,尤为重要,公司3D引擎的资源加载部分采用了硬盘->内存->显存两级加载的模式,超时卸载也分两级,这样虽然实际效果不错,但代码非常繁琐,在FlagshipEngine中,我设法将其进行了一定程度的简化。

首先我们需要定义一个Resource基类,它大致上是这样的:

class _DLL_Export Resource : public Base
    {
    public:
        Resource();
        virtual ~Resource();

        // 是否过期
        bool                IsOutOfDate();
      
    public:
        // 是否就绪
        virtual bool    IsReady();

        // 读取资源
        virtual bool    Load();

        // 释放资源
        virtual bool    Release();

        // 缓存资源
        virtual bool    Cache();

        // 释放缓存
        virtual void    UnCache();

    protected:
        // 加载标记
        bool            m_bLoad;

        // 完成标记
        bool            m_bReady;
       
    private:

    };

        在实际游戏中,加载资源的范围大于视野,当摄像机移动到单元格边缘(必须有一定的缓冲区),就应将新的单元格中的对象加入到资源加载队列中,唤醒资源加载线程调用Load接口进行加载,完成后将该资源的加载标记设为true。而通过可视剪裁所得到的最终可视实体,则需要调用Cache接口构建图像API所需对象,当Load和Cache都完成后IsReady才会返回true,这时该资源才能开始被渲染。
        卸载方面,在加载新的单元同时,卸载身后旧的单元,对单元内所有资源调用Release,Load/Release带有引用计数,仍被引用的资源不会被卸载。当某一资源长时间没有被看见,则超时,调用UnCache释放VertexBuffer等资源。
        为了实现超时卸载功能,我们需要一个ResourceManager类,每帧检查几个已Cache的资源,看起是否超时,另外也需对已加载的资源进行分类管理,注册其资源别名(可以为其文件名),提供查找资源的接口。
        另外为了方便使用,我们需要一个模板句柄类ResHandle<T>,设置该资源的别名,其内部调用ResourceManange的查找方法,看此资源是否已存在,如不存在则new一个新的,GetImpliment则返回该资源对象,之后可以将该资源添加到实体中,而无需关心其是否已被加载,代码如下:

template <class T>
    class _DLL_Export ResHandle
    {
    public:
        ResHandle() { m_pResource = NULL; }
        virtual ~ResHandle() {}

        // 设置资源路径
        void            SetPath( wstring szPath )
        {
            Resource * pResource = ResourceManager::GetSingleton()->GetResource( Key( szPath ) );
            if ( pResource != NULL )
            {
                m_pResource = (T *) pResource;
            }
            else
            {
                m_pResource = new T;
                m_pResource->SetPath( szPath );
                ResourceManager::GetSingleton()->AddResource( m_pResource );
            }
        }

        // 模板实体类指针
        T *             GetImpliment() { return (T *) m_pResource; }

        T *             operator-> () { return (T *) m_pResource; }

    protected:
        // 模板实体类指针
        Resource *      m_pResource;

    private:
    };

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值