Jeck - [Requires JGE rebuild] Extensive cache improvements.

* Numerous cache fixes, reduced filesystem access.
 * Cache fails very gracefully. 
 * Cache is now a templated class, with individual caches per data-type.
 * Much easier to extend.
 * Extensively debugged. Try compiling with -DDEBUG_CACHE.
 * Caches limits can be set on a per-item basis.
 * hgeParticleSystemInfo are now cached, mana particles now fall back to defaults.
 * Samples are not cached, but track filesystem misses using the cache backbone. 
 * Avatars are cached. Default baka avatar is now baka.jpg, to prevent collision with player.

A note on the retrieval types: 
  RETRIEVE_MANAGE puts a resource into a seperate, managed resource list.
    Managed resources are guarenteed valid for the lifetime of the program. 
    Retrieving a managed quad promotes the associated texture to managed. Don't do that by mistake.
    Calls to Resources.Refresh() will attempt to reload managed resources in place.

  RETRIVE_LOCK (and by extension, RETRIEVE_VRAM), returns a resource after locking it.
    A resource may have many locks, and remains in cache until they are all released. 
    If the resource is managed, it returns it unmodified.

A note on quads:
Unlike all other RetrieveWhatever() functions, the default behavior for RetrieveQuad is RETRIEVE_LOCK. Worse, Release(JQuad*) is slow, and will /always/ release one lock from the associated texture.   

There's a long and complicated explanation for this, involving support for live relinking of textures to existing quads, but basically what it means is that we only use RetrieveQuad for quads we intend to store and later Release(). If a temporary quad is needed, the preferred method is to use NEW JQuad* and SAFE_DELETE with RetrieveTexture(). RetrieveTempQuad is also provided, but is only guaranteed until the next call to the cache.

Note that RetrieveCard has none of these problems.
This commit is contained in:
wagic.jeck
2009-09-14 08:28:49 +00:00
parent a696b65ffb
commit d55fc91112
27 changed files with 3732 additions and 2992 deletions

View File

@@ -5,73 +5,109 @@
#include <JTypes.h>
#include "MTGDeck.h"
#include "MTGCard.h"
#include "WCachedResource.h"
#ifdef WIN32
#define CACHE_SIZE_PIXELS 20000000
#define MAX_CACHE_OBJECTS 2000
#else
#define CACHE_SIZE_PIXELS 2000000
//Hard Limits.
#define LARGE_CACHE_LIMIT 5000000
#define SMALL_CACHE_LIMIT 2000000
#define MAX_CACHE_OBJECTS 200
#endif
#define MAX_CACHE_ATTEMPTS 10
#define MAX_CACHE_MISSES 200
class WCachedResource{
public:
friend class WResourceManager;
bool isLocked(); //Is the resource locked?
void lock(); //Lock it.
void unlock(bool force = false); //Unlock it. If force, then set locks to 0.
void hit(); //Update resource last used time.
WCachedResource();
protected:
unsigned int lastTime;
unsigned char locks; //Remember to unlock when we're done using locked stuff, or else this'll be useless.
};
class WCachedTexture: public WCachedResource{
public:
friend class WResourceManager;
WCachedTexture();
~WCachedTexture();
JTexture * GetTexture(); //Return this texture as is. Does not make a new one.
JQuad * GetQuad(float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f); //Get us a new/existing quad.
JQuad * GetCard(float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f); //Same as above, but centered when new.
bool ReleaseQuad(JQuad* quad); //We're done with this quad, so delete and stop tracking. True if existed.
protected:
JTexture * texture;
bool bVRAM;
vector<JQuad*> trackedQuads;
};
class WCachedSample: public WCachedResource{
public:
friend class WResourceManager;
WCachedSample();
~WCachedSample();
JSample * GetSample(); //Return this sample.
protected:
JSample * sample;
enum ENUM_WRES_INFO{
WRES_UNLOCKED = 0, //Resource is unlocked.
WRES_MAX_LOCK = 250, //Maximum number of locks for a resource.
WRES_PERMANENT = 251, //Resource is permanent (ie, managed)
};
enum ENUM_RETRIEVE_STYLE{
RETRIEVE_EXISTING, //Only returns a resource if it already exists. Does not lock or unlock.
RETRIEVE_NORMAL, //Returns or creates a resource. Does not change lock status.
RETRIEVE_LOCK, //As above, locks cached resource.
RETRIEVE_UNLOCK, //As above, unlocks cached resource.
RETRIEVE_RESOURCE, //Only retrieves a managed resource.
RETRIEVE_VRAM, //If we create the texture, use vram. Also locks.
RETRIEVE_MANAGE, //Permanently adds retrieved resource to resource manager.
RETRIEVE_LOCK, //As above, locks cached resource. Not for quads.
RETRIEVE_UNLOCK, //As above, unlocks cached resource. Not for quads.
RETRIEVE_RESOURCE, //Only retrieves a managed resource. Does not make a new one.
RETRIEVE_VRAM, //Retrieve it, and use vram if have to we create it. Must still remove it.
RETRIEVE_MANAGE, //Makes resource permanent.
RETRIEVE_THUMB, //Retrieve it as a thumbnail.
CACHE_THUMB = RETRIEVE_THUMB, //Backwords compatibility.
};
enum ENUM_CACHE_SUBTYPE{
CACHE_CARD,
CACHE_THUMB
CACHE_NORMAL = (1<<0), //Use default values. Not really a flag.
CACHE_EXISTING = (1<<1), //Retrieve it only if it already exists
//Because these bits only modify how a cached resource's Attempt() is called,
//We can use them over and over for each resource type.
TEXTURE_SUB_CARD = (1<<2), //Retrieve using cardFile, not graphicsFile.
TEXTURE_SUB_AVATAR = (1<<6), //Retrieve using avatarFile, not graphicsFile.
TEXTURE_SUB_THUMB = (1<<3),//Retrieve prepending "thumbnails\" to the filename.
TEXTURE_SUB_VRAM = (1<<4), //For textures. If we have to allocate, do it in VRAM.
TEXTURE_SUB_5551 = (1<<5), //For textures. If we have to allocate, use RGBA5551.
};
enum ENUM_CACHE_ERROR{
CACHE_ERROR_NONE = 0,
CACHE_ERROR_NOT_CACHED = CACHE_ERROR_NONE,
CACHE_ERROR_404,
CACHE_ERROR_BAD,
CACHE_ERROR_LOST,
CACHE_ERROR_NOT_MANAGED,
};
template <class cacheItem, class cacheActual>
class WCache{
public:
friend class WResourceManager;
WCache();
~WCache();
cacheItem* Retrieve(string filename, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL); //Primary interface function.
bool Release(cacheActual* actual); //Releases an item, and deletes it if unlocked.
bool RemoveMiss(string id=""); //Removes a cache miss.
bool RemoveOldest(); //Remove oldest unlocked item.
bool Cleanup(); //Repeats RemoveOldest() until cache fits in size limits
void Clear(); //Removes everything cached. Not lock safe, does not remove managed items.
void ClearUnlocked(); //Remove all unlocked items.
void ClearMisses(); //Clear all cache misses.
void Refresh(); //Refreshes all cache items.
unsigned int Flatten(); //Ensures that the times don't loop. Returns new lastTime.
void Resize(unsigned long size, int items); //Sets new limits, then enforces them. Lock safe, so not a "hard limit".
protected:
bool RemoveItem(cacheItem * item, bool force = true); //Removes an item, deleting it. if(force), ignores locks / permanent
bool UnlinkCache(cacheItem * item); //Removes an item from our cache, does not delete it. Use with care.
bool Delete(cacheItem * item); //Call SAFE_DELETE on cacheItem. If maxCached == 0, nullify first. (This means you have to free that cacheActual later!)
cacheItem* Get(string id, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL); //Subordinate to Retrieve.
cacheItem* AttemptNew(string filename, int submode); //Attempts a new cache item, progressively clearing cache if it fails.
string makeID(string filename, int submode); //Makes an ID appropriate to the submode.
string makeFilename(string id, int submode); //Makes a filename from an ID.
map<string,cacheItem*> cache;
map<string,cacheItem*> managed; //Cache can be arbitrarily large, so managed items are seperate.
unsigned long totalSize;
unsigned long cacheSize;
//Applies to cacheSize only.
unsigned long maxCacheSize;
unsigned int maxCached;
unsigned int cacheItems;
int mError;
#if defined DEBUG_CACHE
string lastRemoved;
string lastReleased;
string lastExpired;
#endif
};
struct WManagedQuad {
WCachedTexture * texture;
string resname;
};
//This class is a wrapper for JResourceManager
class WResourceManager: public JResourceManager
@@ -80,64 +116,77 @@ public:
WResourceManager();
~WResourceManager();
JQuad * RetrieveCard(MTGCard * card, int type = CACHE_CARD, int style = RETRIEVE_NORMAL);
JSample * RetrieveSample(string filename, int style = RETRIEVE_NORMAL);
JTexture * RetrieveTexture(string filename, int style = RETRIEVE_NORMAL);
JQuad * RetrieveQuad(string filename, float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f, string resname="", int style = RETRIEVE_NORMAL);
JQuad * RetrieveCard(MTGCard * card, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL); //RetrieveCard is reversed to match current use.
JSample * RetrieveSample(string filename, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL);
JTexture * RetrieveTexture(string filename, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL);
JQuad * RetrieveQuad(string filename, float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f, string resname="", int style = RETRIEVE_LOCK, int submode = CACHE_NORMAL);
JQuad * RetrieveTempQuad(string filename);
hgeParticleSystemInfo * RetrievePSI(string filename, JQuad * texture, int style = RETRIEVE_NORMAL, int submode = CACHE_NORMAL);
void Release(JTexture * tex);
void Release(JQuad * quad);
void Release(JSample * sample);
void ClearMisses();
void ClearUnlocked();
void ClearSamples();
void Refresh(); //Refreshes all files in cache, for when mode/profile changes.
bool Cleanup(); //Force a cleanup. Return false if nothing removed.
void ClearMisses(); //Remove all cache misses.
void ClearUnlocked(); //Remove unlocked items.
void Refresh(); //Refreshes all files in cache, for when mode/profile changes.
unsigned int nowTime();
unsigned long Size();
unsigned long SizeCached();
unsigned long SizeManaged();
unsigned int Count();
unsigned int CountCached();
unsigned int CountManaged();
int CreateQuad(const string &quadName, const string &textureName, float x, float y, float width, float height);
JQuad* GetQuad(const string &quadName);
JQuad* GetQuad(int id);
//Our file redirect system.
string graphicsFile(const string filename, const string specific = "");
string cardFile(const string filename, const string setname, const string specific = "");
string avatarFile(const string filename, const string specific = "");
string cardFile(const string filename, const string specific = "");
string musicFile(const string filename, const string specific = "");
string sfxFile(const string filename, const string specific = "");
int fileOK(string filename, bool relative = false);
//Not part of our interface, but left public to maintain JResourceManager compatibility
//These are for managed resources only.
//For backwards compatibility with JResourceManager. Avoid using these, they're not optimal.
int CreateTexture(const string &textureName);
int CreateQuad(const string &quadName, const string &textureName, float x=0.0f, float y=0.0f, float width=0.0f, float height=0.0f);
JTexture* GetTexture(const string &textureName);
JTexture* GetTexture(int id);
//Wrapped from JResourceManger. TODO: Privatize
int LoadJLBFont(const string &fontName, int height);
int LoadMusic(const string &musicName);
int LoadSample(const string &sampleName);
//Wrapped from JSoundSystem. TODO: Privatize.
JMusic * ssLoadMusic(const char *fileName);
private:
bool RemoveOldestTexture();
bool RemoveOldestSample();
bool cleanup();
void LargeCache();
void SmallCache();
JTexture * attemptTexture(string filename, int mode = 0, int format = TEXTURE_FORMAT);
void DebugRender();
WCachedTexture * getCachedTexture(string filename, bool makenew = true, int mode = 0, int format = TEXTURE_FORMAT);
WCachedTexture * getCachedCard(MTGCard * card, int type = CACHE_CARD, bool makenew = true);
WCachedSample * getCachedSample(string filename, bool makenew = true);
#ifdef DEBUG_CACHE
unsigned long menuCached;
string debugMessage;
#endif
private:
void FlattenTimes(); //To prevent bad cache timing on int overflow
//For cached stuff
map<string,WCachedTexture*> textureCache;
map<string,WCachedSample*> sampleCache;
vector<string> mTextureMissing; //For managed textures.
//Current access time.
int lastTime;
//For cached stuff
WCache<WCachedTexture,JTexture> textureWCache;
WCache<WCachedSample,JSample> sampleWCache;
WCache<WCachedParticles,hgeParticleSystemInfo> psiWCache;
vector<WManagedQuad> managedQuads;
//Statistics of record.
int nb_textures;
long totalsize;
unsigned int lastTime;
};
extern WResourceManager resources;