Search Unity

GPU Instancing: DrawMeshInstanced vs. built-in batching

Discussion in 'General Graphics' started by JoeStrout, Mar 23, 2019.

  1. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I'm trying to wrap my head around GPU instancing right now (see my newbie questions in the other thread). It appears there are two different ways to accomplish this:
    1. Calling DrawMeshInstanced yourself, with appropriate arrays of detail properties. Or,
    2. Making sure your shader/material/etc. supports instancing, and letting Unity do it for you, as in this tutorial.
    I understand that DrawMeshInstanced does no culling or Z-sorting, so I would have to do those myself (to the extent I want/need them). That might be an advantage, if I can use the particulars of my game to do those efficiently or know that they don't apply.

    Conversely, Unity's dynamic batching seems more mysterious. It's hard to know exactly what it's going to do. But maybe it does it more efficiently.

    Can anyone clarify the pros and cons of these two approaches? (I'm targeting OpenGLES3, on Oculus Go, if that matters.)
     
  2. LennartJohansen

    LennartJohansen

    Joined:
    Dec 1, 2014
    Posts:
    2,394
    If you call the DrawMeshInstanced manually you can do all your own internal culling and just keep the instances in memory as Matrix4x4 with the position, rotation and scale. For large amount of instances this will probably give you a better result than having Unity batch all.

    Imagine a terrain with millions of grass patch instances. For unity to render this with GameObjects it would need to process a millions MeshRenderers to find the ones within range and frustum.

    There is an additional step you can take. Use DrawMeshInstancedIndirect.
    This also uses instancing but you have the list of instances in a GPU buffer.
    Then you can use a compute shader as a "pre pass" and do frustum culling etc adding the visible instances to a append buffer. Then draw this buffer. The CPU would not know how many instances was visible but the GPU would and render only this.

    This approach also does not have the 1023 instances per drawcall limit that DrawMeshInstanced have.

    Lennart
     
    VictorKs and leozzyzheng2 like this.
  3. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    A Unity employee stated in another thread that DrawMeshInstancedIndirect doesn't work on OpenGLES, though I've lost the link now. So I might give it a try just to be sure, but I'm not expecting it to work.

    But you make a great point about managing the instances manually vs. GameObjects. Thank you for your input!
     
  4. FariAnderson

    FariAnderson

    Joined:
    Jan 20, 2020
    Posts:
    37
    hey guys, I found this five-year old tutorial from Jason Weimann about GPU Instancing some time ago, and he's doing it simply with instantiating a prefab game object. the trick was just enabling GPU Instancing checkbox from the material inspector and then the objects are automatically Batched reducing Draw Calls. so i'm still not sure if this is the same thing happening with Graphics.DrawMeshInstanced or is there any difference between these two methods:
    1. using Graphics.DrawMeshInstanced
    2. manually instantiate some game objects in the scene that share the same mesh and same material