Improving memory and power use for XNA games for Windows Phone 8

August 19, 2014

XNA Framework games typically use several images, audio files, and other resources that can cause the game to exceed the recommended memory limit for phone applications. There are tools that help you detect the memory use of your game so you can determine whether you need to performance-tune your game. This topic tells you what tools you can use to evaluate the memory use of your game, and provides guidelines to help you reduce it. This topic also describes an API you can use to suppress drawing when your visuals are not animating in order to improve your game’s power consumption.

This topic contains the following sections.

The Windows Phone Performance Analysis tool can help you evaluate your game’s memory use. If your game exceeds the memory limit for lower-memory devices, you can use some of the techniques described in this topic to reduce memory use, or to opt out of lower-memory devices. For more information, see App monitoring for Windows Phone 8. For information about opting out, see App memory limits for Windows Phone 8 or Developing apps for lower-memory phones for Windows Phone 8.

You can reduce memory use in your games by using specific formats for images and sounds. The following sections discuss how you can reduce memory use in your XNA Framework game by using these formats.

Sound Formats

Playback on the phone is lower quality than a typical computer or television that uses external speakers; the difference in sound quality based on choosing to use a particular sound format likely will not be noticeable to the user. The memory consumption of a sound depends on the format of the sound, and on the duration of the sound effect. Sound files with a higher sample rate (48 kHz versus 22 kHz) or higher bit depth (16-bit versus 8-bit) consume more memory than a lower sample rate or lower bit-depth file. To minimize memory use, you should use sounds with lower sample rates and bit depth where possible, particularly for long-playing sounds.

Adaptive Differential Pulse Code Modulation (ADPCM) is a lossy compression format that is supported on Windows Phone, and which can significantly reduce the size of sounds you use in your game. ADPCM typically is best suited for UI and ambient sounds because of its lower quality. For more information about Windows Phone support for ADPCM, see Supported media codecs for Windows Phone 8.

Image Size and Formats

To optimize your game to run on a 256-MB device, you can reduce the size and image quality in your game to an appropriate level for the device. The phone has a smaller display and therefore does not require the level of detail and the high-resolution images you would use on a larger display.

In addition, you can use Direct-X Texture (DXT) Compression format for your images to minimize memory use in your game. The graphics unit implements DXT files in hardware, and they remain compressed when the files are loaded into memory. The graphics card decompresses the files when they render. This is different from how the graphics unit handles PNG and JPG files. Although PNG and JPG files are compressed on disk, they use the same amount of memory as an uncompressed file type. A DXT file has slightly lower image quality than a JPG file of the same image, but the memory footprint is much smaller.

The following table compares the memory use and file size of a typical 256 × 256 MB image.

File type

File size

Memory use

Quality

Alpha channel

32-bit .xnb

256 KB

256 KB

Lossless

Yes

PNG

161 KB

256 KB

Lossless

Yes

JPG

20-90 KB

256 KB

Lossy

No

DXT .xnb

32 KB

32 KB

Lossy

Yes (double size)

To convert your images to DXT format

  1. In your Visual Studio project, display the property grid for the image you want convert to DXT format.

  2. In the property grid, expand the Content Processor section.

  3. Change the Texture Format value to DXT Compressed.

  4. If necessary, change the Resize to Power of Two property to True. DXT images must be sized to powers of two.

    Visual Studio DXT compression property settings

One of the easiest things you can do to reduce the memory use of your XNA Framework game is to limit the number of images and sounds that the game uses. A typical XNA Framework game file is composed of less than 1% code and between 70% and 90% image textures and audio files. There is a memory cost for loading all of these resources. The following sections give you ideas about how you can reduce the quantity of textures and sounds that you use in your XNA Framework games.

Use fewer sounds

The following list contains a few ways that you can reduce the number of sounds in your games.

  1. Reuse a sound instead of using different sounds for similar actions in different parts of the game. Alternatively, reuse a sound but use parametric variations at playback to vary it.

  2. Apply the level-of-detail pattern when you create the sounds for your game.. For example, use a single sound to represent a group of enemies as opposed to using individual enemy sounds played together to represent the same group.

  3. Call the SoundEffect.Dispose method for SoundEffect objects when you are finished using them. This enables the sound effect to be garbage collected, and this reduces the number of sounds in memory.

Use fewer images and textures

Similar to reducing sounds, you can reduce the use of images and textures by using fewer images and by being creative in how you use your images. If you need to represent a group of enemies, use a few enemy images and repeat those many times to represent a group of enemies. This comes at much lower cost in memory use than if you use several unique enemy images to represent the group.

In addition, you can use a sprite sheet object to store many small images as a single image in your game. This results in faster loading and drawing, and a lower memory footprint because you are loading a single image. Also, you can avoid the power of two restrictions of the DXT format when using a sprite sheet.

The most difficult part about using sprite sheets can be composing them. You can compose them by hand, but the easiest way to create a sprite sheet is to use the sample posted on the Xbox Live Indie Games site. This sample uses a custom content processer to combine several images into a single texture, and then records the location of each individual texture. For more information and to download the sample, go to Sprite Sheet. After you create a sprite sheet, use an overload of the SpriteBatch.Draw method, which takes a sourceRectangle parameter, to indicate the position of the texture you want to draw.

As discussed earlier in this topic, the DXT file format is a compressed image format that usually is sufficient to help smaller games meet the 90-MB memory limit. However, if you are working with detailed models and complex terrains, you might need to compress your vertex data to further reduce your game’s memory use.

By default, XNA Framework stores most vertex data as 32-bit floating point values. These floating point values offer high precision, but often games do not require that much accuracy. For example, the VertexPositionNormalTexture structure is 32 bytes in size. This type stores its Position and Normal property values as Vector3 types, which are 12 bytes each, and its TextureCoordinate property as a Vector2, which is 8 bytes. Typically, less precision also means less memory consumption, and there are other, less precise, formats you can use when you develop your game. The following are the VertexElementFormat values that Windows Phone supports.

  • Single

  • Vector2

  • Vector3

  • Vector4

  • Color

  • Byte4

  • Short2

  • Short4

  • NormalizedShort2

  • NormalizedShort4

NoteNote:

The HalfVector2 and HalfVector4 are supported only in the HiDef profile of the XNA Framework, which is supported only on Xbox or PC hardware.

You can use the types in the Microsoft.Xna.Framework.Graphics.PackedVector namespace to generate compressed vectors. The following code shows an example of how you could create your own compressed version of the VertexPositionNormalTexture type. This example extends the ModelProcessor class and overrides the ProcessVertexChannel method to convert normal data to NormalizedShort4 format, and to convert texture coordinates to NormalizedShort2. This results in an 8-byte reduction in vertex size.

using Microsoft.Xna.Framework.Content.Pipeline;
    using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
    using Microsoft.Xna.Framework.Content.Pipeline.Processors;
    using Microsoft.Xna.Framework.Graphics.PackedVector;
 
    [ContentProcessor]
    public class PackedVertexDataModelProcessor : ModelProcessor
    {
        protected override void ProcessVertexChannel(GeometryContent geometry, 
            int vertexChannelIndex, ContentProcessorContext context)
        {
            VertexChannelCollection channels = geometry.Vertices.Channels;
            string name = channels[vertexChannelIndex].Name;

            if (name == VertexChannelNames.Normal())
            {
                channels.ConvertChannelContent<NormalizedShort4>(vertexChannelIndex);
            }
            else if (name == VertexChannelNames.TextureCoordinate(0))
            {
                channels.ConvertChannelContent<NormalizedShort2>(vertexChannelIndex);
            }
            else
            {
                base.ProcessVertexChannel(geometry, vertexChannelIndex, context);
            }
        }
    }

For more information about vector compression, see Compressing Vertex Data.

On mobile devices like phones, the power consumption of your app is critical to providing a good user experience. When your game is in a state in which the graphics are not animating, such as a static pause screen, you should tell XNA not to redraw the screen. Do this by calling SuppressDraw from within your Update method. When you call this method, XNA will skip calling your Draw method until after the next call to Update. Using this technique to prevent unnecessary redrawing of the screen can result in significant power savings.

Show:
© 2014 Microsoft