纹理管理

最近开始正式写纹理管理,用了差不多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 若愚.影歌

原文地址:https://www.cnblogs.com/fishboy82/p/1274406.html