I am loading a Cocos2d Scene that contains almost 700 png Images and even if I run this scene directly from Xcode I receive a Memory Warning message along with a long list of some of my Image names in the console..
I am properly deallocating them in dealloc but when I come again on this scene this time my game crashes during loading my half of the Images
Is this the problem of loading so much textures at once or problematic code?
How should I handle loading so many images and do proper memory management to avoid this crash?
700 png images? Hmmm. Ok, I like those games.
Let's assume each image is "only" 128x128 pixels. Each texture consumes 64 KB (128 times 128 times 4 Bytes). Total of 45 MB memory used for 700 such textures.
If your textures are twice that or even more, KA-BOOM!
Keep in mind that the file size has nothing to do with texture memory. The files may total a few megabytes in the file system. But that's because they're compressed. Textures created from PNG files however are not compressed.
What you can do:
use texture atlases
reduce color depth of textures to 16 Bit
use compressed PVR format
TexturePacker will help you with these tasks.
Related
I am designing a game that makes use of large backgrounds. These are illustrated backgrounds, that are currently sitting at around 4.5 MB and as backgrounds, are sitting in the scene for the entirety of the game.
First, I am not sure if this would cause memory usage to amp up, but I imagine it would, given that there are also other overlaid textures on the screen. That is my first question: can it cause memory issues?
Second, if I have a background that is 2048 x 1536 and at a 300 dpi, and compress/optimise this image, would it reduce memory usage/CPU usage? Is there documentation that relates to how best to optimise these kinds of images?
There are several techniques to do that. It depends on how you're going to use the images.
If it's a background in movement you can split it in tiles, then you render smaller images.
Depends on the format, most of the people just know PNG and JPEG, but there are other projects/formats you can use. Some of them are the smaller size but slower read/write, so is up to you how to use them. i.e.: https://github.com/onevcat/APNGKit
If in your background is not necessary the alpha channel, use JPEG over PNG then you'll save some space.
I'm testing different compressions for my spritesheets for a game on iOS. In a surprising way, I get a more important memory (RAM) use with PVR 2 bits with alpha instead of a PNG 32 (RGBA 4444). I would say the consumption is 25% higher with PVR 2 bits instead of PNG 32 once the spritesheets are loaded inside memory. I'm using Instruments with xCode to verify the memory use on the physical device (iPad Air 2)
I'm using TexturePacker to generate my spritesheets.
I've read evrywhere PVR 2 or 4 is much less memory consumer than PNG 32. How is it possible ?
Edit:
This is strange because according my observations, PVRTC 4 bits RGBA uses a lot more memory (RAM) than PNG 32, neraly 3 times more according Instruments from XCode. PVRTC 2 bits RGBA is 25% higher than PNG 32 RGBA 4444. I'm talking about live RAM consomption, not disque size which has nothing to do and is not a problem. It seems iOS manages PVR differently than it's supposed to do, especially when loading them into RAM.
Edit2:
My textures are 2048x2048, there are POT and have the square format. Evrything work fine, except the RAM consomption is much higher that it should be. I make all my tests with a physical iPad Air 2 device connected to my Mac with a USB cable. I use Instruments inside xcode to verify and follow the RAM consumption in live. I've solved the RAM consomption problem by switching to a PNG 8 bits (indexed) format with a texture divided by 2 (1024x1024). I make a scale x2 in the code to recover a normal size texture. The RAM consumption droped to 240 MB (PNG 8 bits indexed) instead of 950 MB with (PVR 2 bits RGBA). My game is a video puzzles (with 8 seconds video loops at 15 fps) and uses a lot of sprites. (43 spritesheets in each puzzle generated by TexturePacker, around 130 sprites in each spritesheet)
I'm making a Worms-style bitmap destructible terrain game using OpenGL. I'd like to know where the limitiations in terms of video memory are for the size of the worlds.
Currently, I use blocks of 512*512 RGBA textures for the terrain.
How much memory, very roughly, can I expect such a 512*512 RGBA texture to take up?
Is there any internal, automatic compression going on?
How much video memory can I expect most user's computers to have free?
How much memory, very roughly, can I expect such a 512*512 RGBA texture to take up?
Not enough information. You should always use sized OpenGL image formats (GL_RGBA8, GL_RGBA16).
GL_RGBA8 takes up 32-bits per pixel, which is 4 bytes. Therefore, 512*512*4 = 1MB.
Is there any internal, automatic compression going on?
No.
How much video memory can I expect most user's computers to have free?
How much are you using currently?
OpenGL will page image data in and out according to the available space. If you run out of GPU memory, OpenGL will happily allocate system memory and upload the images as needed.
But to be honest, your little Worms game isn't going to actually cost anything in terms of memory size. Maybe 64MB when you're done, tops. It's nothing you need to be concerned about.
I would not worry about that very much. Even with 8192*2048 world (4 screens wide and 2 screens tall, which is very big for Worms-style game) you would require only 8*2*4=64Mb (add mipmaps, other textures, framebuffer) you should fit into 128MB bounds. As far as I know even older GPUs have that kind of memory (we don't speak about GeForce4 cards, right?).
Older GPUs may have limitation on how big each texture could be, but since you already split your world into 512x512 chunks it won't be a problem.
If video memory becomes an issue you could allow users to use half-sized textures (i.e. downsample the world to 4096*1024 and 256x256 chinks) and fetch new / discard unused regions on demand.
With 32-bpp (4 bytes) you get 4*512*512 = 1 MB
See this regarding texture compression: http://www.oldunreal.com/editing/s3tc/ARB_texture_compression.pdf
Again, this depends on your engine, but if I were you I would do this:
Since your terrain texture will probably be reusing some mosaic-like textures, and you need to know whether a pixel is present, or destroyed, then given you are using mosaic textures no larger than 256x256 you could definitely get away with an GL_RG16 internal format (where each component would be a texture coordinate that you would need to map from [0, 255] -> [0.0, 1.0] and you would reserve some special value to indicate that the terrain is destroyed) for your terrain texture, making every 512x512 block take up 0.5MB.
Although it's temping to add an extra byte to indicate terrain presence, but a 3 byte format wouldn't cache too well
I am building an app that uses Cocos2d to create a map of content (technically a big Tree in the graph theory sense). Each node is represented by a sprite with it's own texture, with the leaf nodes all having a second "button pressed" texture. In addition, some of the nodes are PNG animations. I have one sprite sheet containing the 130 or so node textures, and 3 other sprite sheets for the animations. All in all those 4 files add up to only about 18.4 MB.
If I run the app and DON'T run the cocos2d part (i.e. Never launch the framework at all and therefore never load the textures) the app runs at around 10 MB. When I load Cocos2d and those sprite sheets, the memory shoots up past 90 MB.
All my research seems to say I am doing things in the most efficient way possible, but with the memory usage already so high I get a lot of memory related crashes on iPad 1.
Is this normal for cocos2d? Since the images themselves aren't so large, is it using so much memory because of the number of sprites? Are there ways to bring the memory footprint down? I am at a loss, and very much under the gun...
It turns out that the efficiency you achieve by packing the sprites together into big sprite sheets is measured in rendering time, not in memory saved. No matter in a UIImage or into an OpenGL framework like Cocos2d, when you load an image the amount of memory it takes up is width x height x bytes per pixel. So a 2048x2048 png image takes up 2048x2048x4 bytes in memory (12 MB).
To keep memory down in this case I simply have to load things as needed, and unload them as soon as they are not needed. Now the trick is finding out where and when to load, so the user never sees a stutter. FUN!
For iPhone game development, I switched from PNG format to PVRTC format for the sake of performance. But PVRTC compression is creating files that are much bigger than the PNG files.. So a PNG of 140 KB (1024x1024) gets bloated to 512 KB or more in the PVRTC format.. I read somewhere that a PNG file of 50KB got compressed to some 10KB and all, in my case, its the other way around..
Any reason why it happens this way and how I can avoid this.. If PVRTC compression is blindly doing 4bpp conversion (1024x1024x0.5) irrespective of the transparencies in the PNG, then whats the compression we are achieving here..
I have 100s of these 1024x1024 images in my game as there are numerous characters each doing some complex animations.. so in this rate of 512KB per image, my app would get more than 50MB.. which is unacceptable for my customer.. ( with PNG, I could have got my app to 10MB)..
In general, uncompressed image data is either 24bpp (RGB) or 32bpp (RGBA) flatrate. PVRTC is 4bpp (or 2bpp) flatrate so there is a compression of 6 or 8 (12 or 16) times compared to this.
A requirement for graphics hardware to use textures natively is that the format of the texture must be random accessible for the hardware. PVRTC is this kind of format, PNG is not and this is why PNG can achieve greater compression ratios. PVRTC is a runtime, deployment format; PNG is a storage format.
PVRTC compression is carried out on 4x4 blocks of pixels at a time and at a flat bit rate so it is easy to calculate where in memory to retrieve the data required to derive a particular texel's value from and there is only one access to memory required. There is dedicated circuitry in the graphics core which will decode this 4x4 block and give the texel value to your shader/texture combiner etc.
PNG compression does not work at a flat bitrate and is more complicated to retrieve specific values from; memory needs to be accessed from multiple locations in order to retrieve a single colour value and far more memory and processing would be required every single time a texture read occurs. So it's not suitable for use as a native texture format and this is why your textures must be decompressed before the graphics hardware will use them. This increases bandwidth use when compared to PVRTC, which requires no decompression for use.
So for offline storage (the size of your application on disk), PNG is smaller than PVRTC which is smaller than completely uncompressed. For runtime memory footprint and performance, PVRTC is smaller and faster than PNG which, because it must be decompressed, is just as large and slow as uncompressed textures. You might gain some advantage with PNG at initialisation for disk access, but then you'd lose time for decompression.
If you want to reduce the storage footprint of PVRTC you could try zip-style compression on the texture files and expand these when you load from disk.
PVRTC (PowerVR Texture Compression) is a texture compression format. On devices using PowerVR e.g. most higher end mobile phones including the iPhone and other ARM-based gadgets like the iPod it is very fast to draw since drawing it is hardware accelerated. It also uses much less memory since images are represented in their compressed form and decoded each draw, whereas a PNG needs to be decompressed before being drawn.
PNG is lossless compression.
PVRTC is lossy compression meaning it approximates the image. It has a completely different design criteria.
PVRTC will 'compress' (by approximating) any type of artwork, giving a fixed bits per texel, including photographic images.
PNG does not approximate the image, so if the image contains little redundancy it will hardly compress at all. On the other hand, a uniform image e.g. an illustration will compress best with PNG.
Its apples and oranges.
Place more than one frame tiled onto a single image and blit the subrectangles of the texture. This will dramatically reduce your memory consumption.
If you images are, say, 64x64, then you can place 256 of them on a 1024x1024 texture in a 16x16 arrangement.
With a little effort, images do not need to be all the same size, just so long as you keep track in the code of the rectangle in the texture that each image is at.
This is how iPhone game developers do it.
I agree with Will. There is no point in the question. I read the question 3 times, but I still don't know what Sankar want to know. It's just a complain, no question.
The only thing I can advice, don't use PVRTC if you mind to use it. It offers performance gain and saves VRAM, but it won't help you in this case. Because what you want is just reducing game volume, not a consideration about trade-off between performance and quality.