Search Unity

SpriteAtlas memory consumption

Discussion in 'Editor & General Support' started by yanivng, Oct 4, 2018.

  1. yanivng

    yanivng

    Joined:
    May 21, 2017
    Posts:
    43
    Hi,

    I'm in the process of optimizing my application memory consumption.
    In the process, I'm using Unity profiler while connecting to an Android device, which run a development build of the application.

    The application, is using two types of sprite containers:

    1. Sprite sheets created by the Texture packer.
    2. Sprite Atlases created by unity.

    Using the profiler, it is observed that while the sprite sheets (created by the Texture packer) take the expected amount of RAM, the sprite atlases created by unity consume DOUBLE the expected amount of RAM.

    For example, the sprite atlas UIATLAS, whose size is 4096x4096 is supposed to consume 16MB of RAM:

    UIAtlas1.png

    But looking at the profiler, after running "Take Sample", you see the value 32MB:

    UIAtlas2.png

    Any help is welcome here.

    One more comment (please review): UIAtlas belongs to an asset bundle called "atlas_ui". It is defined on several directories containing its sprites, all of which belong to the same asset bundle, atlas_ui. Is that the correct way to define it?

    Thanks in advance!
     
  2. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    Just a guess, but does your sprite atlas have "generate mipmaps" enabled? I've heard that MipMaps make your texture take up twice as much space.
     
  3. yanivng

    yanivng

    Joined:
    May 21, 2017
    Posts:
    43
    Thanks for the replay! mipmaps are disabled.
    Here are my sprite atlas settings:

    UIAtlas3.png
     
  4. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,456
    Read/Write Enabled means the texture is in GPU memory and retained in CPU memory after upload to the GPU, hence taking twice the space. Unless necessary, Read/Write should always be disabled.
     
    Peter77 and yanivng like this.
  5. yanivng

    yanivng

    Joined:
    May 21, 2017
    Posts:
    43
    Thanks!
    1. Why would I want to have a sprite atlas both in GPU and CPU memory?
    2. Disabling Read/Write means it will be only in GPU memory?
     
  6. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,456
    you're welcome :)
    1. You wouldn't I guess. It's kept in CPU so it is readable and if written to can get re-uploaded. Unless you need to read pixels from the atlas or modify them.
    2. After uploading, yes. It will pass through CPU memory for uploading it to the GPU driver memory. So while uploading, it's in memory twice but afterwards only in the GPU driver memory.
     
  7. yanivng

    yanivng

    Joined:
    May 21, 2017
    Posts:
    43
    Thanks a lot for your help. I will disabled Read/Write, re-run the profiler on an Android device and update with the results here.
     
  8. yanivng

    yanivng

    Joined:
    May 21, 2017
    Posts:
    43
    Great! unchecking Read/Write saved me quite a lot of MBs :)
     
  9. Moonjump

    Moonjump

    Joined:
    Apr 15, 2010
    Posts:
    2,572
    Mipmaps do take up more space, but only 33% more, not 100% more.

    Having them enabled can improve performance and image quality, so it is often a bad idea to turn them off (but not always, it should be tested in each case).
     
  10. yanivng

    yanivng

    Joined:
    May 21, 2017
    Posts:
    43
    One more thing; For one of the atlases, I need to use GetSprites(). To do that, the atlas must be set as ReadWrite enabled.
    1. If GetSprites() is done only during initialization, right after loading the spriteatlas from asset bundle, is it safe to change the atlas settings to disable ReadWrite? How do I do that?
    2. If instead of using Unity SpriteAtlas, I use Texture Packer to create an atlas with its tpsheet, I can still get a reference to its sprites and set them in sprite renderers individually, without the RAM penalty using Unity SpriteAtlas. Any downsides I don't see here?

    Thanks again for the help!
     
  11. yanivng

    yanivng

    Joined:
    May 21, 2017
    Posts:
    43
    Solved it, description:
    Since I only need the references to the sprites and not the textures themselves, I am loading the sprites from the asset bundle and disabling ReadWrite for the atlas. This way, duplication is removed for both the GetSprites (which clones the sprites) and for saving the spriteatlas in CPU memory space.
     
  12. cdr9042

    cdr9042

    Joined:
    Apr 22, 2018
    Posts:
    173
    If you are loading the sprite directly from asset bundle, the atlas is not needed. Your build will include both the Sprite and its atlas, but you only use the Sprite. You should remove the atlas
     
  13. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    539
    Sorry to bring up this old post but Im curious about the usage of atlases in this case... do you actually save any ram performance by creating atlases? or it would be exactly the same using separated sprites?
     
  14. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    Atlases often take-up more RAM/VRAM because they almost always contain some empty space.

    Saving memory was never the purpose of using an atlas. The point of using an atlas is only to reduce the amount of materials that the renderer has to set-up. This can result in better performance depending on your scene.
     
    cdr9042 likes this.
  15. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,456
    Well, the memory consumption also depends on the sizes and form factors of the individual sprites and compression Algos used. The latter often don't work on NPOT resolutions, while atlases will usually be POT resolutions. So the added extra padding might no end up actually costing anything while allowing for better compression
     
    Last edited: Oct 18, 2023
  16. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    539
    Thanks a lot. Finally a clear answer.

    What I thought it could be useful in some contexts is to have the atlases are grouped by usage so for example lets say we have a set of textures that are just used in certain popup or certain scene... we could use addressables or Resources.Unload and just load or unload that atlas from memory when we enter/exit that popup or scene or whatever, would this be a correct use?
     
  17. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    My version "correct use" is to avoid micromanaging memory usage if possible (unless my memory consumption is actually causing a problem).

    If you're loading and unloading lots of different scenes with unique assets, I guess it might be good to call Resources.UnloadUnusedAssets occasionally. So far I haven't made a project big enough where this was necessary.
     
    pistoleta likes this.
  18. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    Also, read what MartinTilo wrote. You'll see the answer's not really clear at all. Always be suspicious of "clear answers," they're usually just over-simplifications.
     
    pistoleta likes this.