Storing binary images and portability

Started by
3 comments, last by SmkViper 9 years, 3 months ago

Hey!

I'm trying to find the best way to store binary images of resources to make loading as fast of possible.

My resources are all POD (no constructors, no vtables) so I don't have to deal with those cases.

Regarding endianess, my resource compiler converts the data endianess to the endianess of the target platform, so I think I won't need any endianess conversion at runtime (eg: the pc version ships with little endian compiled resources)

My biggest problem is how to deal with x86 and x64 since the pointers on each platform are different sizes.

I store a pointer patching table and the end of each resource, however I want to use the same binary image on both x86 and x64 but structs that contain pointers have different sizes depending on the architecture.

How can I deal with this?

Do you know any tricks?

Thanks.

Advertisement

I want to use the same binary image on both x86 and x64 but structs that contain pointers have different sizes depending on the architecture.

How can I deal with this?


Reserve 64 bits of space for pointers on both platforms, and on x86 just treat the unused 32 bits as padding. Since you'll need to compile a separate EXE for x64 and x86, you can just #ifdef 32 bits of padding into your struct on x86, or create a templated pointer type that does the padding for you in one place.
I don't generally read and write pointers at all because you're never going to load up objects at the same address you saved them to. So since I'm always going to be patching up those pointers at runtime, I write ID numbers instead, and those can be a consistent size. Since these ID numbers don't have the same restrictions as pointers, and you're running on 32-bit architecture, then your ID number can be 32-bits in size (though if disk space isn't a problem you can use 64 bits if you want)

Basically, before I save, I run through all objects and tell them to "pre save" which they then use to register themselves with the ID counter which hands them an ID to use and associates that ID with their pointer value. Then when the object is later saved and wants to save a pointer it asks the ID manager for the ID associated with the pointer, and writes the ID instead.

On load, each object reads in its ID and tells the ID manager about it along with it's current pointer. Then after all loading is done, you run a "post load" pass where each object takes the IDs it loaded for its pointers and asks for the real pointer from the ID manager.

If you want to avoid the "post load" process (and also the risk of storing ID numbers in a pointer variable) you can have your ID manager spit out a type/ID table at the beginning of the data so all the objects can be pre-allocated and assigned IDs before they load their data. Then, when an object loads an ID it can ask the ID manager for the pointer immediately.
Nowadays, the CPU is incredibly fast relative to disk access. Loading compressed data and decompressing it might be faster than loading uncompressed data, depending on how many files you have, how big they are and what kind of compression ratios they get.

Another potential idea is to bundle all the resources into a single (compressed) archive (like a zip file). A single file might is hopefully very contiguous on disk, which should reduce time spent seeking the disk. A virtualised file system can be used, something like Physfs, allowing the rest of the program to be isolated from the details of how the resources are actually located or loaded. Indeed,

Consider benchmarking the different approaches to be sure.

Compiling resources into your executable might slow down your iteration time (unless it is something you can turn on and off quickly), which could be detrimental to the project and should be factored in.
And if you want to really get that last tiny bit of speed out of your load times, you should use a format that allows you to easily re-order the contents, so you can put resources that are loaded together next to each other on disk - preferably in the order the game requests them, reducing the amount of seeking the hard drive has to do.

This topic is closed to new replies.

Advertisement