Search Unity

One or many atlases?

Discussion in 'Scripting' started by GeorgeCH, Nov 10, 2017.

  1. GeorgeCH

    GeorgeCH

    Joined:
    Oct 5, 2016
    Posts:
    222
    Hi all -

    I've a few questions about the atlases as they were added by Unity in 2017.1 - for context, I'm working on a 2D mobile game:
    1. Does having more than one page in the atlas result in additional draw calls (an extra draw call every time an atlas page has to be "switched")?
    2. Am I correct in that larger atlas max texture size essentially translates into fewer pages (since more stuff can fit into a single page) but bigger mobile build size? Conversely, do smaller texture sizes mean more pages (and more draw calls) but smaller build sizes?
    3. Is there ever a reason - from the performance standpoint - to have a dedicated atlas for the UI and another one for game object sprites (bullets, ships, etc), or should they all sit in the same atlas? Would switching between atlases trigger additional draw calls?
    I've been trying to figure these out by trial and error, but with iOS build times being what they are (and with me working off a Mac Mini to boot!), trial and error quickly translate into torture and failure :)
     
  2. bostudio

    bostudio

    Joined:
    Nov 28, 2017
    Posts:
    20
    This thread is particularly interesting and it's just sad to leave it without answers.
    So if you have found some answers for your questions, please post them.
     
  3. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    6,971
    To be honest, I don't know the technical true answers to all these questions. But to make an educated guess/stab at it...

    This I wouldn't be able to say for certain. But if a page results in a 2nd texture, and since Atlases are about gaining performance by packing sprites into a single texture, and that a material is dependent on its texture... then yes, it'd probably result in more draw calls. (the same would go if you use the same page across multiple materials)

    Bigger mobile build... Well that'd depend. A texture's size is larger if it has larger dimensions. BUT you'd have fewer textures.

    4 512x512 textures and 1 1024x1024 texture both have the same overall dimensions. In raw form they effectively take up the same amount of memory (give or take a small amount for header/formatting information).

    But here in comes in some variance.

    1) Packing - the size/overlap of sprites can vary. And how they pack is heavily dependent on the space it packs into. If you have a sprite that is 2/3's the width of a page in a 512 texture, you can only fit 1 across the bottom. If you span this across 2 512 textures, it's 2 across the bottom in total. But if it were a 1024 texture... you could fit 3 across the bottom of the same width (1024 overall). Thusly a larger well packed page may fit more sprites than smaller ones.

    Vice versa, if your page is too large and you don't fill it all the way up. You'll end up with a bunch of unused space. If your sprites could fit into 3 512x512 pages, using a 1024 page will consume the dimensions of 4 smaller pages, leaving an entire page's worth of empty space taking up memory.

    2) Compression - The texture once loaded into memory is generally going to be in some raw format for direct drawing (you don't want to decompress an image every draw pass). Rather instead you compress the texture to discuss and decompress it into video memory. This means that the "build size" is dependent on compressed size, while graphics memory is 'generally' relies on decompressed size (there's technicalities to that of course depending on graphics device).

    Since your build size is going to rely on compressed sizes of textures. This means the size of the image can vary based on that compression algorithm.

    Compression algorithms rely heavily on patterns. Things they may do are like create an image palette. This means instead of storing each pixel as their full 24-bit RGB colour (or 32 if ARGB), it'll instead tally up all the colours used in the image and store that as a palette. Then each pixel will store the index of the colour it is supposed to be from that palette. This means an image with fewer colours can potentially take up less space then an image with more colours.

    Other things that impact compression are contrast/edges. Large sections of similar colour pack more than noisy areas in images. So a big green circle will take up less space than a scattered jackson pollack painting.

    So this can again impact your images both small and large.

    If you have a large number of similar sprites using similar palettes that can fill a large page. Compression would favor that larger texture since all that pattern information is only generated for the single large texture. Instead of for multiple textures.

    Where as a large diverse page "might" take up more space since it's packing all that diverse information. Especially if you scatter your sprites across the 'page' thusly increasing variance between sections.

    Where as if you packed all similar sprites together (such as palette/variance), it'd be smaller. If you had sprites of 4 different palettes, packing them into smaller images "might" benefit you. Though it could also be said that just laying them out in a larger texture, but clumped similarly (think of the large texture as 4 regions and organize accordingly), you again could save from compression.

    With all that said... exploiting compression can get VERY complicated and would require an intimate knowledge of the compression algorithm. And if you're at this point in trying to save that extra 10 kilobytes of memory... I'd start wondering about your obsessive compulsive nature.

    I could see having an atlas for each for various reasons, not just performance.

    But as performance goes. It could benefit you if you happen to have a materials for each specific thing. If you have a specific UI material, and a UI atlas. Grouping them makes sense. You're making sure that the texture used by the UI material has everything available and thusly can draw in fewer draw calls.

    But if your UI is spread across multiple materials, well then it doesn't really matter. It'd be better to match the atlas to its material, rather than to its scope.

    But usually those just happen to line up. I would bet your UI all generally uses the same material (or same small set of materials).

    ...

    ...

    TLDR;

    Overall consider the point of the Atlas

    The main purpose is to reduce memory:
    https://docs.unity3d.com/Manual/class-SpriteAtlas.html

    By packing the sprites together to reduce the amount of unused/blank texture space you reduce video memory usage.

    ...

    The draw call thing is sort of an added benefit that happens to fault out of the structure as well.

    But in relation to the draw call thing... just by having an atlas you've reduced draw calls significantly from if you hadn't used an atlas at all.

    If you really need to optimize further... well start profiling first and foremost before you start heading down this path. Because organizing to that degree can get very complicated very quickly.
     
  4. ron-bohn

    ron-bohn

    Joined:
    Oct 5, 2015
    Posts:
    104
    Not sure about the new sprite atlas feature, but generally speaking I stick to the following...

    1) atlas static objects together
    2) put dynamic objects into a second atlas material.
    3) only atlas objects that share the same shader/material and only atlas static objects together, only atlas dynamic objects together.
    4) total atlas size/dimensions on mobile devices is much lower so you might have to pack less into a single atlas depending on your target platform. In many cases, it might be better to use 4 1024's instead of 1 4096

    So yeah, there's times where you won't get a performance gain by using an atlas between game objects....for example, DON'T waste space on your static object atlas with a dynamic game object materials. Keep dynamic and static object on separate atlases for max CPU / set-pass call savings. Yes, I'm kinda repeating that, but it's so important and totally answers your question ;)

    Textures/sprites/atlases, are the first thing that will cause GPU overhead (in many projects).
    Re-using prefabs as much as possible is the easiest way to minimize GPU memory and limit redrawing.
    Technically, atlases mainly reduce set-pass calls, or CPU overhead....the reduced GPU memory benefits or total VRAM are simply a bi-product of using less textures and resources.

    GPU instanced game objects also benefit from atlases and that is interesting if you're dx11 or higher. There's also some other things that apply to 3D projects so please don't take this as gospel. As mentioned, profiler and even the stats window during play mode can tell you a lot. I also like to make sure vsync is off and see what the fps reads in the stats window
     
    yyylny and Kurt-Dekker like this.
unityunity