On Draw Calls & Batching

polycounter lvl 7
Offline / Send Message
Bartalon polycounter lvl 7
We're getting to the optimization stages of our project and are having some troubles controlling our batch count.

I've combed through various posts on the matter, many of which are rather old by the standards of technological progression. As an artist, there are some things I would love to have clarified so I can make better decisions when it comes to generating/optimizing art assets. This thread might be a bit long so I'll try to segment it as best I can.

  • Question 1
This thread discusses draw calls and how/when they are batched. Different models with the same materials and textures can be batched, sure; but specifically, can two different models with a different amount of material IDs be batched? Since meshes get chopped up by material ID as part of the render state, do the IDs that are present on both models get batched together or does nothing batch since they don't share the exact same material IDs?

  • Question 2
I read the Render Hell article and it was difficult to grasp (again, I'm a paint-slinging artist person, not a graphics programmer). It explains draw calls and render states, and how render states are the more "expensive" part of processing data. From what I understand, every time a new batch has to render, the render state changes, which is slow. So, fewer batches means fewer render state changes which results in faster processing of data.

I've also noticed that Unity's "stats" panel in the game window no longer displays draw calls, but instead counts batches. Is this because batches are the biggest problem compared to draw calls?

I'm sure there's a balance somewhere, but it would be nice to know some sort of rough estimate of how any batches is "equal to" a draw call in regards to performance.

For instance, which is most efficient:
  1. 500 draw calls and 500 batches
  2. 200 draw calls and 800 batches
  3. 800 draw calls and 200 batches
Obviously less of both is better, however if it's possible to increase one in order to reduce the other and subsequently gain performance... Yeah, I want to do that.

  • Question 3
This is sort of a continuation of Question 2. The project I am on uses mostly tiling textures, so our structures have upwards of 10, even 25 material IDs depending on their size. Many of the structures share the same material IDs but there are a LOT of polygons so I'm assuming many of these identical materials have to get split into different rendering chunks which, if I understood Render Hell correctly, increases the batch count.

Let's say I grouped all our structures into smaller groups. If I gave each smaller group their own "set" of materials that wouldn't be used with other groups, that would probably increase the draw call total quite a bit, however the batch count should go down substantially since the GPU wouldn't have to split as many polygons into chunks for rendering the same one material.

Here are some arbitrary numbers to help visualize the two scenarios:
  1. 10 structures with a total of 25 materials shared between them all. They're pretty high poly so batching is likely to happen on most materials.
  2. 10 structures with 5 materials assigned to each structure but not used on any of the other 9 structures. So, 50 materials total but they are assigned to fewer total polygons which means fewer split chunks and fewer batches?

  • Question 4
I often hear that engines don't like "long, thin triangles" and it has to do with how the pixels are cut off in areas where they don't fit in (overdraw, or something like that I think). What exactly determines whether a triangle is too long and thin? Is it based on how much screen space that object takes up, or how acute the edges are? What if there are two identical models with long, thin triangles but one is scaled much larger than the other? Are they still both causing problems?

Thanks in advance for anyone who took the time to read and answer part/all of my questions.

TL;DR Optimization is a huge pain and I'd like to know if batches are worse for performance than draw calls. Also someone should really make an Earthquake-style thread with practical applications of the concepts of draw calls and batching.


  • Farfarer
    Online / Send Message
    Farfarer Polycount Sponsor
    So, batching is good, but there if a bit of overhead involved with each dynamic batch. What that means is that there's a trade off point where you'll see benefits from dynamic batching but only after a certain number of them. There are no hard and fast rules here, you're just going to have to test this and find out where it lies for your project.

    That probably even changes per platform.

    Static batching is well worth doing. Unity will pre-batch any objects that are static at build time. That means you don't get the overhead hit you get from dynamic batching. Just mark anything that doesn't move as static and enable static batching.

    I should be clear, what gets batched are triangles with identical (i
    e. the same) materials. And that share static/dynamic state.

    As for the thin triangle question, that's in screen space. Effectively it's any part of a triangle that is drawn and is narrower than a fragment (2x2 pixel block), but narrower than a pixel is probably the ones to look out for.
  • SlyRipper
    Offline / Send Message
    SlyRipper polycounter lvl 5
    I found a script (combinechildren) somewhere on the unity forums, i think, that combines meshes that are static. I guess it reduces draw calls and stuff, so you can design your environment, and simply combine this to a big mesh and keep your original meshes in the scene (deactivated ofc) for later use and editing. Could also be that this isn't necessary anymore with newer versions of Unity.

    It might also help to collect those textures together into an Atlas, I guess with those two methods you'll get some more performance benefits, although I'm not pretty sure about it :)

    Oh, btw Farfarer, might it be possible that you update your TF2 Shader for Unity 5? (with additional Outline Effects) would be nice, hehe.
  • Farfarer
    Online / Send Message
    Farfarer Polycount Sponsor
    You shouldn't need the combine children script for Unity 5 because you can static batch now. Used to be a Pro only feature.
  • Elith2
    Offline / Send Message
    Elith2 polycounter lvl 7
    Just to chime in on the batching thing from experience on Unity 4 (i know we are talking about Unity 5 here but i have no idea if it's been fixed) batching just didn't work at all (we had pro on all projects) and we ended up using the combine children script to actually get round this issue.

    It might be fixed in Unity 5 though, but it's really worth a testing early.

    If i remember correctly though the profiler did say it was batching things, but when we actually took a close look at what was going on we realised it wasn't giving the savings the batching was saying should have been made.
  • kio
    Offline / Send Message
    kio polycounter lvl 10
    static batching only happens at runtime - so you wont see it in the statistics in a "non play mode" game view - I really didnt know it and started to combine meshes manually, just to find out later... but oh well ;)

    the frame debugger in unity5 is also quite handy to see how the final image gets constructed and to see where the draw calls come from.
Sign In or Register to comment.