NPOT Texture allocation bug

Forums Programming cocos2d internals NPOT Texture allocation bug

This topic contains 89 replies, has 18 voices, and was last updated by  goodeats2009 11 months, 1 week ago.

Viewing 25 posts - 1 through 25 (of 90 total)
Author Posts
Author Posts
April 9, 2012 at 3:18 am #240556

riq
Keymaster
@admin

A few weeks ago I recommended to use NPOT (Non Power Of Two) textures due to a bug on iOS that was allocating 33% more memory for POT textures.

But these past days I have been doing more research on this an apparently iOS is allocating up to 99% more memory for NPOT textures.

These are the tests that I did:

2048x2048 + RGBA texture:  21.34 Mb  (instead of 16Mb... 33% POT mipmap bug).
2047x2047 + RGBA texture: 31.99 Mb ( instead of 16Mb. 99% more )
1025x1025 + RGBA texture: 7.26 Mb ( instead of 4Mb. 81% more )
1536x1536 + RGBA texture: 15.75 Mb (instead of 9 Mb. 75% more )

I measured everything with Instruments + VM Tracker and paying attention to the dirty memory.

Before recommending everybody to stay away of NPOT textures, I would appreciate if you could do some tests with your game and confirm whether or not this is a bug.

How to test it:

1. Run your game with Instruments + Allocations

2. Once Instruments is running, switch to VM Tracker

3. Once one of your NPOT textures is loaded/displayed, take an snapshot and see the “Dirty” memory.

Repeat the same exact steps but using POT textures instead.

Please, report on this thread the “dirty” values both for POT and NPOT textures.

If you are using cocos2d v2.0, then NPOT textures are enabled by default.

If you are using cocos2d v1.0, then you have to enable NPOT textures on the ccConfig.h file:

#define CC_TEXTURE_NPOT_SUPPORT 1   // <-- enable NPOT for cocos2d v1.x

Thanks.

PS:

I opened a post at the Apple forum:

https://devforums.apple.com/thread/147591

April 9, 2012 at 3:26 am #371904

QcMat
Participant
@qcmat

Thanks for letting us know, this news is at a very very good time for me to investigate, as we just submitted and can pull. I’ll try to do those tests tomorrow first thing.

April 9, 2012 at 9:55 am #371905

alchemygames
Participant
@alchemygames

In our current game, with cocosd2 v1.0.1, we where hitting several memory warnings with the iPad 1, and after enabling NPOT texture support they where gone. So in the iPad 1 it was allocating less memory for sure.

In the rest of devices there were no probles, so no further test where done.

April 9, 2012 at 2:22 pm #371906

riq
Keymaster
@admin

@alchemygames:

Interesting. Which iOS version were you using on your iPad 1 ? What technique did you use to measure the memory? Thanks.

April 9, 2012 at 4:14 pm #371907

frilla
Participant
@frilla

Here are the results for a .pvr.ccz file using RGBA8888. I’m not sure exactly what value you wanted (which type, which column) so here are the deltas after loading the spritesheet:

2048x2048:
Type Resident Size Dirty Size
*All* +21MB +16MB
*Dirty* +21MB +16MB
*IOKit* +21MB +16MB

2047x2047:
Type Resident Size Dirty Size
*All* +16MB +16MB
*Dirty* +16MB +16MB
*IOKit* +16MB +16MB

on iOS 5.1 with cocos2d 1.0.1 on iPhone 4S

April 9, 2012 at 6:18 pm #371908

rickms
Participant
@rickms

Riq, I’ve done some tests on and was unable to confirm your findings. Is it possible this is an OpenGL 2.0 only issue?

First Test (Ran 3 times)

iPhone 4 / iOS 5.1 / Cocos2d 1.1b
1024x2047 RGBA - Expected texture size ~8MB

Dirty memory: ~37MB.
I dug deeper into the details and found a corresponding IOKit allocation of exactly 8MB

Second Test (Ran 3 times)

iPhone 4 / iOS 5.1 / Cocos2d 1.1b
1024x2048 RGBA - Expected texture size ~8MB

Dirty memory: ~40MB.
The 8MB Allocation in the first test was replaced by a 10.64MB allocation.

The increase of the 8MB allocation by ~33% to 10.63 accounts for the entire memory discrepancy.

I repeated these tests on an iPad 1 with IOS 4.3 and got similar results.

EDIT:

Riq, do you have a test project that duplicates this? I’d love to compare results.

April 9, 2012 at 6:30 pm #371909

riq
Keymaster
@admin

@frilla:

I am a bit confused by your numbers since “dirty” is 16MB both on POT and NPOT. very strange…

In order to make sure that we are talking about the same “dirty” size, number, this is the one that I need. Thanks!

April 9, 2012 at 6:38 pm #371910

riq
Keymaster
@admin

@rickms:

Thanks for your feedback. Apparently it seems to be an OpenGL v2.0 bug, or a cocos2d v2.0 bug, or my tests are completely flawed.

Yes, I do have a test project here:

https://github.com/ricardoquesada/test-ios-npot-texture-memory

April 9, 2012 at 7:23 pm #371911

rickms
Participant
@rickms

@riq

Hmm odd there seems to be an extra malloc of the same size of the texture by gfxAllocateTextureLevel, but it seems to only happen for NPOT textures. Looking more and more like an implementation bug/’feature’.

April 9, 2012 at 7:23 pm #371912

frilla
Participant
@frilla

@riq:

The numbers I posted includes the one you circle in red.

I checked the code, CC_TEXTURE_NPOT_SUPPORT is not taken into consideration when loading .pvr.ccz, could this be a reason for the results?

April 9, 2012 at 7:43 pm #371913

rickms
Participant
@rickms

And just another follow-up, to confirm @riq that gfxAllocateTextureLevel is being called by glTexImage2D for NPOT textures only.

April 9, 2012 at 8:50 pm #371914

riq
Keymaster
@admin

@frilla: Yes, PVR images are not affected by the CC_TEXTURE_NPOT_SUPPORT. What is strange is that your “dirty” value is similar for POT and NPOT.

@rickms: Thanks. Which cocos2d version were you using for your tests ? Are you still on v1.0 or did you test it with my test project ?

Thanks.

April 9, 2012 at 9:09 pm #371915

frilla
Participant
@frilla

So after testing again a few times, I can’t even reproduce +21MB in resident memory when loading POT texture of my earlier post. Right now, the results after many tries are the same wether the file is POT or NPOT for my .pvr.ccz RBA8888.

I also checked the “real memory” value in Activity Monitor instrument and this value never increments more than 16MB when loading the file, POT or NPOT. So right now, I’m wondering if I’m affected by this 33% bug at all. Am I suppose to be affected by this bug if I’m using .pvr.ccz?

For the testing, I check the values in Instruments, then load the file when a button is pushed using [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@”myFileName.plist”]; and then check the values in Instruments again. Is my method flawed?

April 9, 2012 at 9:27 pm #371916

riq
Keymaster
@admin

@frilla: I am not sure if CCSpriteFrameCache loads the texture into memory or not. In order to be sure, could you also create an sprite and add it to the scene ?

Thanks.

April 9, 2012 at 9:40 pm #371917

rickms
Participant
@rickms

@riq that was using your test project, shows up in the VM Tracker and under allocations.

April 9, 2012 at 9:43 pm #371918

riq
Keymaster
@admin

@rickms: thanks. So you were using cocos2d v2.0. I will do the same test, but with cocos2d v1.0 to see what happens.

April 9, 2012 at 10:08 pm #371919

rickms
Participant
@rickms

@riq I tested the 1.1 tree originally and the only memory difference was the allocated mipmap memory for POT textures so I think it’s pretty safe to say it’s a GL2.0 implementation issue. Interested to see what else you find.

April 9, 2012 at 10:31 pm #371920

riq
Keymaster
@admin

Same tests using cocos2d v1.0 (OpenGL ES 1.1):

https://github.com/ricardoquesada/test-ios-npot-texture-memory/tree/cocos2d-v1.0

PVR 2048x2048 + RGBA:  21.34 Mb  (instead of 16Mb... 33% POT mipmap bug).
PVR 2047x2047 + RGBA: 31.99 Mb ( instead of 16Mb. 99% more )
PNG 2047x2047 + RGBA: ~16.00 Mb (expected value)
PNG 1025x1025 + RGBA: ~4.00 Mb (expected value)
PNG 1536x1536 + RGBA: 9.00 Mb (expected value)

Mmm… why the PVR are generating more memory ? This seems to be a cocos2d bug

April 9, 2012 at 11:17 pm #371921

riq
Keymaster
@admin

With cocos2d v2.0 and using PNG instead of PVR:

2047x2047 + RGBA texture:  ~24 Mb ( instead of 16Mb. 50% more )
1025x1025 + RGBA texture: 7.26 Mb ( instead of 4Mb. 81% more )
1536x1536 + RGBA texture: 16 Mb (instead of 9 Mb. 75% more )

Mmm… I will try to use GLKit…

April 10, 2012 at 12:11 am #371922

riq
Keymaster
@admin

Using GLKit + cocos2d v2.0:

2047x2047 + RGBA texture:  16 Mb ( OK )
1536x1536 + RGBA texture: 9 Mb ( OK)
1025x1025 + RGBA texture: 4 Mb ( OK )

So, it seems to be a cocos2d bug (or cocos2d is triggering a bug on iOS).

If I can’t find the bug I will add a “If iOS > 5.0, then use GLKit texture loader”

GLKit tests are here: https://github.com/ricardoquesada/test-ios-npot-texture-memory/tree/glkit

April 10, 2012 at 1:25 am #371923

riq
Keymaster
@admin

Update:

The PVR loading is fixed by moving the glTexParameters before loading the texture.

I still need to figure out how to fix this for PNG images.

UPDATE2:

PNG is working OK too.

So, there are two iOS bugs here:

- BUG #1 If you set the glTexParams after creating the texture, then it will allocate more memory. I did know that calling glTexParams after creating the texture was slower. But the bug is that it is allocating more memory.

- BUG #2: NPOT RGB888 textures (which should be avoided in the 1st place) allocates 100% more memory. Apparently when the texture is expanded internally for 32-bits, it allocates extra memory and is not released until the texture is unloaded.

April 10, 2012 at 2:43 am #371924

cybergreg
Participant
@cybergreg

@riq – thanks for your (continued) amazing work… :-D

April 10, 2012 at 3:14 am #371925

frilla
Participant
@frilla

@riq: So I created a sprite with the pvr.ccz instead of loading the plist file and got similar numbers as yours.

2048x2048: dirty size +21MB
2047x2047: dirty size +32MB

I did play with glTexParameteri in CCTexture2D#setTexParameters (comment or moving them) and the dirty size increase was then 16MB (POT & NPOT) file but with visual bugs. I guess I’ll wait for the official fix.

April 10, 2012 at 7:48 am #371926

alchemygames
Participant
@alchemygames

@riq: The iPad is running iOS 5.0.1.

However, we didn’t do any formal test, but without NPOT texture support the game was hitting so many memory warnings it eventually crashed, and with NPOT textures enabled, with the exact same code, no memory warning was triggered.

April 10, 2012 at 3:45 pm #371927

rickms
Participant
@rickms

@riq nice work. My tests on 1.1 were indeed PNG only which is why I didn’t notice the PVR difference.

Viewing 25 posts - 1 through 25 (of 90 total)

You must be logged in to reply to this topic.