Thread: Resource manager works great

  1. #1
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607

    Resource manager works great

    Now that I have a working cache and resource manager how do I go about finding the right size cache for the game?

    Right now it's set at 4mb which is ridiculously low and gets into a cache thrash rather quickly.

    Luckily when the cache miss ratio is above 60% meaning 6 out of 10 cache requests miss the cache will raise the max size to accomodate the situation.


    It's a little weird not having texture members in my objects and my code now looks like this:

    Code:
    void CSkySphere::Render(void)
    {
    
      //Request texture from resource cache
      CTexture *pTexture=(CTexture *)X3DGetResMgr()->STLGet(m_strTexture);
      
      //If we didn't get it we must re-create the resource
      
      if (!pTexture) 
      {
        pTexture=new CTexture();
        pTexture->CreateFromFile(m_strTexture);
      }
          
      //Set the texture
      m_spDevice->SetTexture(0,pTexture->GetTexture());
    ...
    ...
    Code:
    HRESULT CTexture::CreateFromFile(std::string strFile)
    {
      //::MessageBox(0,"Creating texture resource",0,0);
      
      //Call base and load the data from the file into the buffer
      bool bFailed=Create(strFile);
      HRESULT hr=0;
      
      if (!bFailed)
      {
        //Create texture interface from buffer data
        hr=D3DXCreateTextureFromFileInMemory(X3DGetDevice(),
                                             (LPCVOID)m_pBuffer,
                                             m_uFilesize,
                                             &m_pTexture);
      
        //If texture creation fails it is a major error
        if (FAILED(hr)) ::MessageBox(0,"Failed to create texture from memory",0,0);
      
        //If all went well then add us to the resource cache and tree
        if (hr==D3D_OK) X3DGetResMgr()->STLAdd(this);
      
        return hr;
      }
      else
      {
        //Major error here
        ::MessageBox(0,"Cannot create texture resource",0,0);
        return hr;
      }
      
        
    }
    Code:
    bool CResMgr::STLAdd(CResource *pObj)
    {
      
      //Name
      std::string strTemp;
      
      //iterator for find
      std::map<std::string,STLListNode *>::iterator it;
      
      //If top is NULL the list is empty and therefore the tree is too
      if (m_pTop==NULL)
      {
        //Create new node and place at top of cache
        STLListNode *pNewNode=new STLListNode();
        pNewNode->pPrev=NULL;
        pNewNode->pNext=NULL;
        pNewNode->pResource=pObj;
           
        m_pTop=pNewNode;
        m_pBottom=pNewNode;
      
        //Insert node into map  
        strTemp=pNewNode->pResource->GetName();
        it=m_mapRes.find(strTemp);
        if (it==m_mapRes.end())
        {
          m_mapRes.insert(std::make_pair(strTemp,pNewNode));
          m_dwCurSize+=sizeof(*pNewNode)+pNewNode->pResource->GetSize();
              
        } else return true;
        
      }
      else
      {
        //Create new node and place at top of cache
        STLListNode *pNewNode=new STLListNode();
        pNewNode->pPrev=NULL;
        pNewNode->pNext=m_pTop;
        pNewNode->pResource=pObj;
        
        strTemp=pNewNode->pResource->GetName();
        it=m_mapRes.find(strTemp);
        
        if (it==m_mapRes.end())
        {        
          
          //Set bottom if node is added and only 1 node in list
          if (m_pTop->pNext==NULL) m_pBottom=m_pTop;
       
          m_pTop=pNewNode;
      
          //Insert node into map  
          m_mapRes.insert(std::make_pair(strTemp,pNewNode));
          m_dwCurSize+=sizeof(*pNewNode)+pNewNode->pResource->GetSize();
        } else return true;
          
      }
      
      return false;
    }
    I'm glad I finally have this working because it has been a major pain in the arse.

    Here is a screenshot after about 15 seconds of running the game. The only thing using the cache here is the space texture you see in the background. As more and more objects start using the cache the ratios will change rather quickly. It will take a bit of time to convert the existing object classes over to the cache system but when I get that done I will show some more. I've got some models, sounds, music, planets, and other items ready to place in this sector.
    Last edited by VirtualAce; 03-12-2011 at 11:41 AM.

  2. #2
    Registered User
    Join Date
    Apr 2006
    Posts
    43
    It's a little weird not having texture members in my objects and my code now looks like this:
    Here are some suggestions on how you could do...

    Use a texture member in your classes and make them aware of the resource manager so they can delegate all the work to that class...

    Makes the code where you use the resources much more readable IMHO.

    Also, you might start thinking about having a memory pool of all small objects instead of doing new on them since new is really really slow, but that depends on how many objects you usually create every frame.

    Code:
    // Init sky (Adding the resource manager as a member might be good, but the singelton way also has its pros...)
    CSkySphere sky_sphere(strTexture) { 
    
      m_pTexture = new CTexture(strTexture);
    }
    
    
    
    void CSkySphere::Render(void)
    { 
      //Set the texture, GetTexture just wraps all the caching stuff and makes the game code cleaner.
      m_spDevice->SetTexture(0,m_pTexture->GetTexture());
    ...
    }
    
    // Move all the resource handling here...
    tTexID CTexture::GetTexture(void)
    {
      //Request texture from resource cache
      tTexID texID =(tTexID)X3DGetResMgr()->STLGet(m_strTexture);
      
      //If we didn't get it we must re-create the resource
      
      if (!tTexID) {
        // LoadFromFile is basically same as your CreateFromFile but I thought 
        // you should be able to just return the D3D/OpenGL texture ID instead 
        // of a class...maybe not?
        tTexID = pTexture::LoadFromFile(m_strTexture);
    
        if (tTexID)
          // Added the string as key value so we can search for the data in LoadFile...
          // You might want to do the wrapper class thingy instead.
          X3DGetResMgr()->STLAdd(tTexID, m_strTexture);
      }  
    
      return tTexID;
    }
    Happy coding...

    /f

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Right now when you create a resource it loads the contents of the file into the buffer in the CResource base class. STLGet returns a CResource object. But it requires an object name - which I'm using the filename as the unique name.

    Now CTexture could be a member of CSkySphere and maintain the name and it does, but CTexture can be NULL at any time. Notice that it adds 'this' to the cache. That means the entire class is added and not just the data in the class. So if I do not check when texture is NULL I will be in trouble.

    The Update() function of the resource cache attempts to maintain the size by dropping off the bottommost objects in the cache. When these are deleted they will be CResource derived objects so m_pTexture will become NULL. The only way to get the texture back is to re-create the resource. But I cannot do it through the m_pTexture pointer if it's NULL.

    I could have the resource manager create the resource using RTTI to determine the type but I'm not sure.

    I don't like the ugliness right now either but I cannot delegate that code to another class because the pointer to the object could be NULL at any time.

    The only other way to do this is instead of adding CResource objects I would add buffer objects to the cache. But if I do this a cache hit will still mean I must create the Direct3D interface from the data in memory which is redundant if I have already done this before.

  4. #4
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by Bubba View Post
    Now that I have a working cache and resource manager how do I go about finding the right size cache for the game?
    Empirically. Therefore, it would be a good idea to make the initial cache size load-time configurable to avoid the need for recompilation.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  5. #5
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Yes the initial cache size is read from an options file for now.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Templated Generic Resource Manager, WIP..
    By Shamino in forum C++ Programming
    Replies: 13
    Last Post: 02-19-2006, 06:29 PM
  2. Generic Resource_Manager WIP with lots TODO
    By Shamino in forum C++ Programming
    Replies: 19
    Last Post: 02-01-2006, 01:55 AM
  3. Can't load string from resource DLL's string table
    By s_k in forum Windows Programming
    Replies: 4
    Last Post: 07-15-2003, 06:43 AM
  4. Resource File Help
    By gcn_zelda in forum Windows Programming
    Replies: 1
    Last Post: 06-07-2003, 08:36 AM
  5. resource problem/question
    By stallion in forum Windows Programming
    Replies: 4
    Last Post: 01-29-2003, 02:08 PM