Remove custom texture from memory

Remove custom texture from memory
0
#1

When i create a sprite using a custom texture (not a filename) as follows

    auto rt = RenderTexture::create(cutZone->getContentSize().width,cutZone->getContentSize().height,Texture2D::PixelFormat::RGBA8888);
    rt->beginWithClear(0, 0, 0, 0);
    toBeClipped->visit();
    cutZone->setBlendFunc(BlendFunc{GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA});
    cutZone->setFlippedY(true);
    cutZone->visit();
    rt->end();

    Sprite *s = Sprite::createWithTexture(rt->getSprite()->getTexture());

i noticed that the texture is not added into memory like filenames. When i try to free unused memory, using: Director::getInstance()–>getTextureCache()->emoveUnusedTextures(); i believe that the memory from this custom textures is not freed.

Also i noticed that sometimes a key called “cc_2x2_white_image”.

Printing info about this prints the following. What is this texture?
“/cc_2x2_white_image” rc=926 id=2 2 x 2 @ 32 bpp => 0 KB

Also can somebody from cocos team explain me memory management works in these cases of custom textures and how i can free it up? @zhangxm

0 Likes

#2

Indeed this is interesting. We can have Minggo explain.

0 Likes

#3

I believe that CC_2X2_WHITE is just a safe key for when a texture is not found. so the program does not crash. I found an example of such case:

However, i still can’t understand how custom textures are maanged in memory if they dont have a key like filenames. Mayve they are released automatically when the sprite is removed vs filenames which remain in shared texture cache?

0 Likes

#4

@kerryk TextureCache::removeUnusedTextures() only releases textures whose reference is 1, which means not other codes use it.

Does the memory here means the texture created by OpenGL? If so, it is deleted in Texture2D’s destructor.

0 Likes

#5

@zhangxm i tried to reproduce my case in HelloWorld. Here is the code:

bool HelloWorld::init(){

if ( !Scene::init() ) return false;

Sprite *spriteWithFilename = Sprite::create("HelloWorld.png");
this->addChild(spriteWithFilename);

const int loops = 1000;

auto callbackAddChilds = CallFunc::create([this,spriteWithFilename,loops](){
    
    for (int i=0; i<loops; i++){
        
        auto rt = RenderTexture::create(100,100,Texture2D::PixelFormat::RGBA8888);
        rt->beginWithClear(0, 0, 0, 0);
        spriteWithFilename->visit();
        rt->end();
            
        spriteWithFilename->setTexture(rt->getSprite()->getTexture());
    }
});

this->runAction( Sequence::create(DelayTime::create(3),callbackAddChilds, NULL));

return true;
} 

What i did, is that i run the code for 10, 100 and 1000 loops. I assume 2 things will happen:

  1. rt will be released automatically at the end of the current loop.
  2. When i set the texture of an existing sprite in the scene, i expect the previously set texture to be released.

Therefore, all of these loops should ended up in the same memory. However, every time we call setTexture, it seems that memory goes up without the previous texture being released. This test was done in a real device. Am I missing something?

10 loops

100 loops

1000 loops

I also tried to remove the sprite from the scene and then nullify it to see if that will clear all memory but it seems that only the last texture is cleared.

 void HelloWorld::tryFreeMemory(){
       this->removeAllChildrenWithCleanup(true);
      _spriteWithFilename = nullptr;
 }

HelloWorldScene.cpp (3.3 KB)
HelloWorldScene.h (1.8 KB)

0 Likes

#6

I think Xcode memory tools doesn’t include the memory used by GPU. You can debug the program, all texture created by rendertexture are freed.

0 Likes

#7

I hope so ) As code indicated, you release previous here. I just thought it was strange if xcode indicated that memory was used to not indicate memory was freed.

09%20PM

0 Likes

#8

I think it will minus the memory that is freed, or it is useless.

0 Likes