Skip to main content
GameDev.net gamedev.net
🔒 Locked

Resource/Asset/Texture Management

Started by RobM Nov 19, 2009 at 1:31 AM 6 replies 1.4k views
Original Post
RobM
RobM
With resource or asset management, what is the best way to store, say, textures as they are loaded in (syncronously or asynchronously)? My current idea is that as a level loads and a texture is requested (by filename as that's what will be stored with each mesh or mesh subset), it is loaded and added to a map which is keyed on an unsigned integer ID. The ID is then stored with each object or mesh (subset) that uses it for fast lookups. When I come to draw a model that uses that texture, I just look up the texture in the map using the id (which should be way faster than using the filename string) and away we go. The filename of the texture is stored with my texture instance. One thing I'm a bit unsure of is that if I have two seperate models that use the same texture, the first model loaded to use the texture will load it, and when loading the second model, we'd have to check every texture instance in the map comparing the filename to see if it has already been loaded. Something doesn't smell quite right with this approach, can anyone suggest a better one?
Ravyne
Ravyne
In my system, there's a std:map holding the resource -- both the key and the resource type are template type parameters, and the resource can be a polymorphic type.

When you request that a resource be loaded, you get back a smart_ptr to the resource. In my current use, I'm using Boost's implementation, because it's being adopted by the next round of C++ standards (and many library implimentations already have shared_ptr in their tr1:: extensions).

So basically, the only time you ever look up a resource is when you no longer hold a smart pointer -- in general, the string-based lookup is only used when loading resources. When a level want's to "hold on" to a resource without forcing it to stay in memory, my system copies the smart_ptr handle into a weak_ptr and releases the smart_pointer. What that does is allow the resource to be memory collected if necessary, but gotten back easily (and cheaply) if the resource wasn't memory collected. If it was, we have to load it again, but there's not much that can be done about that.

The final thing my system has is the concept of resource classes -- In my system there are three: "momentary" resources which are always collected as soon as they are free (during the collection phase, which only runs when needed or told to), Temporary resources, which live for a significant but finite time, and Permanent resources, which are intended to live for the life-time of the ResourceCache (Many people call this "the manager") which owns it.

I guess that brings up the last fairly unique point about my system, which is that it doesn't rely on a Singleton to universally manage resources. This means you are free to create as many resource managers as you see fit -- perhaps one per level, so that it can simply be deleted at the end of it, or one for bitmap images and another for .TGAs. Heck, if you wanted, with my system, you could even have a Cache of Caches :)

I am slowly writing an article on it for the site, complete with source, but I have precious-little time these days and it has been very slow in coming.
throw table_exception("(? ???)? ? ???");
haegarr
haegarr
I'm using instances of concrete Resource classes as a kind of proxies. E.g. each instance of the TextureResource class stands for a, well, texture of course. Such resources are loaded with the level and are available for the lifetime of the level. The Resources so far may store informations like which file has to be read to fetch the resource data itself, whether the fetching should be done at level load time or on demand, how to cache the resource data, memory footprint of the data, and so on. Specializations may hold additional data; e.g. TextureResource may hold the texture dimensions. Objects in the scene refer to heirs of such Resource class instances.

Now, when a Resource gets instanciated (if it is a Prototype) or somehow else used in the Scene, then the actual resource data gets loaded from mass storage if necessary, making the Resource instance "complete". The invoker then gets access to the requested data.


There are other things that can be done with such a concept, and more details in fact. E.g. it is possible to generate resource data from other resource data by Converter instances (say, the data of a TextureResource can be computed by an appropriate Converter from the data of an ImageResource which itself are loaded from mass storage). This is outside the scope of this thread, but I wanted to mention it because it was an important reason for me to implement such a system, just for the case you may wonder ;)
nsto119
nsto119
Quote:
Original post by Ravyne

The final thing my system has is the concept of resource classes -- In my system there are three: "momentary" resources which are always collected as soon as they are free (during the collection phase, which only runs when needed or told to), Temporary resources, which live for a significant but finite time, and Permanent resources, which are intended to live for the life-time of the ResourceCache (Many people call this "the manager") which owns it.


I like this. Seems like a simple solution to a problem I've had with my resource loaders.
RobM
RobM
Some good ideas there guys, thanks.

One other thing on a similar topic. Has anyone noticed that on the Call of Duty series (multiplayer and 4,5,6 in particular), when you start a new game, under your first black and white view of the level, you can actually see textures upgrading. Does anyone have any thoughts as to why this happens?

If the level is still loading as you're moved to your initial spawn point, maybe it uses the 10 second countdown to finalise things. This could also mean that parts of the map and hence textures are loaded from disk as you move around it. After all, you only need to have the first MIPMAP for a texture loaded that's first seen ~100 yards away. By the time you approach the texture, the rest of the MIPMAP chain would have been loaded.

I just can't believe they would use asynchronous loading with Call of Duty, for a start I don't see any disk access lights come on throughout the level. This would also mean manually putting together MIPMAPs for a texture intraframe - that doesn't seem right does it?
EJH
EJH
Quote:
Original post by RobMaddisonMy current idea is that as a level loads and a texture is requested (by filename as that's what will be stored with each mesh or mesh subset), it is loaded and added to a map which is keyed on an unsigned integer ID. The ID is then stored with each object or mesh (subset) that uses it for fast lookups. When I come to draw a model that uses that texture, I just look up the texture in the map using the id (which should be way faster than using the filename string) and away we go. The filename of the texture is stored with my texture instance.

One thing I'm a bit unsure of is that if I have two seperate models that use the same texture, the first model loaded to use the texture will load it, and when loading the second model, we'd have to check every texture instance in the map comparing the filename to see if it has already been loaded.

Something doesn't smell quite right with this approach, can anyone suggest a better one?


Thats a simple way to do it, and few engines I have seen do it that way. BTW, what's wrong with doing a lookup when loading an asset to see if it has already been loaded? Every engine must do that in some manner, since you don't want to leave it up to the designer to make sure they only load 1 version of each unique asset...

userman8888
userman8888
as soon as you load your models, rearrange the polygons of the models, group them by same texture resource.
monophonic
monophonic
Quote:
Original post by RobMaddison
...when loading the second model, we'd have to check every texture instance in the map comparing the filename to see if it has already been loaded.

Something doesn't smell quite right with this approach, can anyone suggest a better one?


You could keep a second map instance, mapping the filename to the id of already loaded textures. When loading a texture, you would first check this second map, and use the value from there if one is found. If not, you would load the texture just as you do now, but also add a mapping from the filename to the id into this second map.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.