• 纹理管理


    最近开始正式写纹理管理,用了差不多2周基本功能已经完成,总结下来纹理管理需要作的事情有

    1。根据纹理名字迅速找到纹理。

    2。当显存不够使用的时候,而用户又要使用一张目前不在显存的纹理,那么需要选择一张纹理替换

    3。将纹理按照长,宽,表面格式分组,相同的属于同一个组,这样做的目的是为了能够更好的实现(2)的功能

    4。创建纹理时将图像数据载入纹理

    在目前的实现中,功能(1)通过对字符串的哈希来实现,对于字符串的hash网上文章比较多,我使用的是Blizzard所使用的hash方法:

    unsigned long GFTextureManger::HashString( const char *String, unsigned long dwHashType )
    {
     unsigned char *key = (unsigned char *)String;
        unsigned long seed1 = 0x7FED7FED;
        unsigned long seed2 = 0xEEEEEEEE;
        int ch;
        while( *key != 0 )
        {
            ch = toupper(*key++);
            seed1 = m_CryptTable[(dwHashType << 8) + ch] ^ (seed1 + seed2);
            seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
        }
        return seed1;
    }

    功能1实现非常简单,但是考虑到即将使用的LRU替换算法,我并没有使用Std的标准hash_map,而是自己做了一个可以同时Hash和双向连接的Double link hash map这样每当一张纹理被使用的时候可以从这个Link hash map中移动最前面,同时又不会影响hash,这样在链表中(double link hash map) 的最后一个节点就是Least Recently Used texture

    为了实现功能2,我的初步计划是这样对于 长Width 高Height MipLevel 表面格式为FMT的所有纹理称为一个纹理组,所有在这个纹理组中的纹理都可以互相替换,也就是说如果需要使用一张纹理而这张纹理还没有被载入显存,同时没有足够的显存分配,那么只要找到这个纹理所在的纹理组,其中任何纹理的显存部分都可以被目前这张纹理所使用。为了实现上述功能定义了2个纯虚类:

    class GFTexMemPart
    {
    public:
         GFTexMemPart();
      virtual ~GFTexMemPart();
         GFFORMAT m_Format;
         int      m_Width;
         int      m_Height;
         int      m_MipLevels;
         bool     m_CreatedSucceded;
    };

    class GFTexVideoMemPart:public GFTexMemPart
    {
    public:
       virtual ~GFTexVideoMemPart();
       virtual unsigned int GetVideoMemSize() = 0;
    };
    class GFTexSysteMemPart:public GFTexMemPart
    {
    public:
       virtual ~GFTexSysteMemPart();
       virtual unsigned int GetSysMemSize() = 0;
    };

    在目前的D3D中的实现就是2个texture,一张在显存,一张在系统内存中。

    /*Implementation Of D3D video Texture part*/
    class GFD3DTexVideoMemPart:public GFTexVideoMemPart
    {
    public:
     GFD3DTexVideoMemPart(int Width, int Height, int Levels, GFFORMAT Fmt , unsigned long MemSize);
     ~GFD3DTexVideoMemPart();
     unsigned int GetVideoMemSize(){ return m_VideoMemSize;}
     IDirect3DTexture9 * m_VideoMemTex;
    protected:
     bool CreateTexture( int Width, int Height, int Levels, GFFORMAT Fmt);
        unsigned long m_VideoMemSize;
    };
    /*Implementation Of D3D system Texture part*/
    class GFD3DTexSysteMemPart:public GFTexSysteMemPart
    {
    public:
     GFD3DTexSysteMemPart(int Width, int Height, int Levels, GFFORMAT Fmt, unsigned long MemSize);
     ~GFD3DTexSysteMemPart();
     unsigned int GetSysMemSize(){ return m_SysMemSize;}
     IDirect3DTexture9 * m_SysMemTex;
    protected:
     bool CreateTexture( int Width, int Height, int Levels, GFFORMAT Fmt);
        unsigned long m_SysMemSize;
    };

    这样一个Texture应该分别由 video 和system part组成。当显存不够分配的时候只需要从同组中的LRUtexture上取下它的video Memory part 并且挂到但前地Texture就可以了。对于一个组中的所有texture使用双向链表将他们连接起来每当一个Texture被使用以后就简单得将这个Texture方到该组的最前面这样就实现了LRU表,每当需要替换的时候只要取链表中最末尾的节点就是最least Recently Used Texture 了

    .class GFTexture:public GFRefObject
    {
    public:
       GFTexture();
       virtual ~GFTexture() ;
       virtual bool CreateTextureFromGfpFile( const TCHAR * gfpTexfile,GFTEXUSAGE Usage = GFTEXUSG_INVIDMEM) = 0;
       virtual bool CreateTexture( int Width, int Height, int Levels, GFTEXUSAGE Usage, GFFORMAT Fmt) =0;
       virtual bool LoadTexture( const TCHAR * gfpTexfile) = 0;
       virtual void DestoryTexture() = 0;
       virtual bool UpLoadToVideoMemory() = 0;
     //Below Part is Designed for texureManagement
       virtual GFTexVideoMemPart * GetVideoMemPart() =0;
       virtual GFTexSysteMemPart * GetSysteMemPart() =0;
       virtual GFTexVideoMemPart * DetachVideoPart() =0;
       virtual GFTexSysteMemPart * DetachSystemPart() =0;
       virtual void AttachVideoPart(GFTexVideoMemPart *) =0;
       virtual void AttachSystemPart(GFTexVideoMemPart *) =0;
       virtual long GetWidth() =0;
       virtual long GetHeight() =0;
       virtual int  GetMipLevel() =0;
       virtual GFFORMAT GetFormat() =0;
       virtual unsigned int GetTexVidMemSize() = 0;//in Byte
       const  std::string & GetName(){ return m_Name;}
       void   SetName(const char * name){ m_Name = name;}
       double GetLastUsedTime(){return m_LastUsedTime;}
       void   SetLastUsedTime(double Time){m_LastUsedTime = Time;}
       void   SetTextureGroup(GFTextureGroup  * Group);
       GFTextureGroup *  GetTextureGroup();
    protected:
       std::string m_Name;
       GFTextureGroup *  m_TexGroup;
       double m_LastUsedTime;//Get Last Time Texture has been used
    };

     以上基本的数据结构 当制订Texture替换策略时还需要考虑到其他组的Texture是否能够释放以供使用同时策略应该能够更具缺页略动态调整

    fish.shadow song 若愚.影歌

  • 相关阅读:
    毛笔算法 毛笔签名效果
    手写输入控件
    全栈工程师成长路线
    配置msdtc
    流行的广告轮播(图片轮播)JS代码!!
    水晶报表放上去网站会爆:bobj错误的
    查询所有存储过程
    VB.NET and C# Comparison
    SQL查询案例:多行转换为一行
    SQL Server行列转换[转]
  • 原文地址:https://www.cnblogs.com/fishboy82/p/1274406.html
Copyright © 2020-2023  润新知