Textures didn’t load on 64 bit device due to byte alignment.

I submitted my game Diesel Racer 2 for review to the Apple app store.

My game was rejected due to the fact that on a 64 bit iOS device some of the textures were black.

The textures that were black were PowerVR compressed textures.

The reason they didn’t load was due to Byte alignment.

In C++ structs may have variables of different byte length. For instance an unsigned short is usually 2 Bytes while an int as 4 Bytes.

In 32 bit structs are compiled so the variables are aligned to 4 Bytes(= 32 bit).

In 64 bit structs are compiled so that variables are aligned to 8 Bytes(= 64 bit).

When loading a PVR textures the first thing I read is the file’s header.

This is the version 3 PVRTC header:

 

typedef struct _PVRTexHeaderV3{
    uint32_t    version;
    uint32_t    flags;
    uint64_t    pixelFormat;
    uint32_t    colourSpace;
    uint32_t    channelType;
    uint32_t    height;
    uint32_t    width;
    uint32_t    depth;
    uint32_t    numSurfaces;
    uint32_t    numFaces;
    uint32_t    numMipmaps;
    uint32_t    metaDataSize;
} PVRTexHeaderV3;

When packed to 4 bytes alignment this struct is 52 Bytes long.

However, when packed to 8 bytes alignment this struct is 56 bytes long! But in the file the header is saved to 52 Bytes and does not have 4 bytes of padding at the end like in memory.

The solution is to always read 52 Bytes from the file(unless one day we will have 128 bit systems?).

We can read it as is into the memory of the struct in 64 bit, since the alignment only adds 4 bytes to the end of the struct in this specific case.

Do note that byte alignment might add bytes in the middle of the struct in both 32 bits and 64 bits.

Here is such example:

 

typedef struct _Foo{
    uint16_t    a;
    uint64_t    b;
} Foo;

In 64 bit systems, Foo will be 16 Bytes long and the extra 6 padding bytes will be between a and b.

In 32 bit systems, Foo will be 12 Bytes long and will have 2 padding bytes in between a and b.

Apple has documents about what you need to consider when porting your app from 32 bit to 64 bit, too bad I forgot to read it before I submitted the first build.

https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaTouch64BitGuide/ConvertingYourAppto64-Bit/ConvertingYourAppto64-Bit.html

However, I fixed it in the following build.

Diesel Racer 2! Now available.

IconV2_512

“A former illegal racing driver is living a peaceful life with her new family.

Until one day she realize she has to race again for the same people who got her son into trouble.

The competition is young, the competition is fierce but she race for life.”

 

I have released the game “Diesel Racer 2” for several mobile and micro console platforms.

It is now available on Amazon, Google Play and OUYA(The OUYA build is not up to date). It will be also soon availalbe on iOS.

The game plays with either the motion sensors(on mobile) or a game pad(OUYA, FireTV).

It is a good looking 3D racing game.

Originally I wanted Diesel Racer 2 to have a much larger scope but I had to cut out a lot of the features.

I would like to add a lot more features in the near future, so consider it in the current state as a kind of an Alpha.

There are two track to race.

Features I would like to add:

  • More tracks.
  • Multiplayer.
  • Weapons and car upgrades.
  • Story mode.
  • Death match areana.
  • And more…