Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Instance Batcher - Reduce draw calls by batching larger number of instances

Discussion in 'Assets and Asset Store' started by Kekec, Nov 12, 2015.

  1. Kekec

    Kekec

    Joined:
    Jul 12, 2015
    Posts:
    24
    Instance Batcher is a mesh batching solution that will help you reduce draw calls when using large number of prefab instances, while still allowing for dynamic changes.

    Asset Store
    Documentation

    You can download the demo here:
    You can make a simple test to see if Instance Batcher can run on your target device.



    === Features =======================

    Requires almost no change in workflow.

    Reduces draw calls by batching larger number of instances of a single mesh, while still allowing dynamic use of individual instances.

    No vertex limit on the original mesh (vertex limit of 65534 vertices per Mesh still applies)

    Allows dynamic changes to:
    • Transform component
    • MeshRenderer component properties:
    • shadow casting mode
    • receive shadow
    • material
    • shared material
    Allows setting per instance color (RGBA).

    Dynamic renderer bounds calculation for each batch (render only visible batches).

    Changes are applied in LateUpdate.

    Modified Standard shaders:
    • Metallic and Specular workflow
    • Forward and Deferred render path
    • Directional, Point and Spot lights (with shadows and cookies)
    • using per instance color (for albedo (RGB) and transparency (A))
    Easy to use InstanceBatcher_Utils.cginc for adding instancing support to custom shaders:
    • Includes basic instructions
    • Simple custom shader provided as a sample
    Editor Tool for generating Instance Batcher Prefab.

    Source code included.



    === Requirements and Limitations ==========

    Target device must have support for:
    InstanceBatcher_Utils.cginc works only with vertex/fragment shaders.

    Does not support per instance culling.

    Does not support multiple materials or sub-meshes on a game object with InstanceController component attached.

    Does not work with light probes and/or reflection probes.

    Does not support SkinnedMeshRenderer

    Does not support LOD Group

    Modified Standard shaders do not support parallax.

    Things that will make instance not batch with others and will create a new batch:
    • Each combination of MeshRenderer's shadow casting mode and receive shadow will create a separate batch.
    • MeshRenderer's material property behaves as normal and will produce a new material, which means that it won't batch with other instances.
    • Adding new instance when the capacity of the largest batch is reached will produce a new batch of smallest capacity.


    =====================================

    Video showing FPS gain in a dynamic scene (also 2552 draw calls VS 40 draw calls :))


    Video showing the simple procedure of making Instance Batcher prefabs using the Editor tool and then creating some instances.



    Here are some profiling pictures done to compare Instance Batcher with Dynamic batching. The scene consisted of 16900 game objects, a plane and directional light. All game objects were casting and receiving shadows. There was no dynamic changes being made to the cubes just because the overhead of iterating all 16900 objects would kill the performance (and the point with this profiling was to also show the difference in the "CPU Usage").

    There were two test cases:
    • First one was done using cubes, which can take advantage of Dynamic batching.
    • The second one was done using spheres. Dynamic batching on spheres does not work since the built-in primitive mesh for sphere has too many vertices.

    On the image showing "CPU Usage" the "drawing" process part was selected just to clearly show the biggest difference (since the "Gfx.WaitForPresent" part makes the performance look worse than it really is).

    profiler_compare_cubes rendering.png
    profiler_compare_cubes.png
    profiler_compare_spheres rendering.png
    profiler_compare_spheres.png



    In case you are not sure if using Instance Batcher would benefit your project, don't hesitate to ask any question. Comments and suggestions are also welcomed :)
     
    Last edited: Dec 5, 2015
    elias_t likes this.
  2. carking1996

    carking1996

    Joined:
    Jun 15, 2010
    Posts:
    2,605
    Ya got a demo?
     
  3. Kekec

    Kekec

    Joined:
    Jul 12, 2015
    Posts:
    24
    Hi,

    Sorry for late reply.
    There is no WebGL / WebPlayer demo if this is what you meant. As far as I know they both use Shader Model 2.0 which means Instance Batcher would not work on those platforms. I took some time to try and build it for both and it didn't work (even after changing some shader code to remove errors from targeting these platforms).

    Maybe if you can say more about what kind of demo would you like to see, I can take some time and put it together.;)
     
  4. carking1996

    carking1996

    Joined:
    Jun 15, 2010
    Posts:
    2,605
    Anything to test it out, exe/mac builds would be good with screenshots and stuff. I don't see why shaders would make a difference. I don't have any issues with U5 and gl/web player.
     
  5. Kekec

    Kekec

    Joined:
    Jul 12, 2015
    Posts:
    24
    I'll try to play around a little more with the gl/web build tomorrow, but unless it can use the Vertex Texture Fetch (which is specified in Shader Model 3.0) to sample RGBAFloat texture from vertex shader, then there is no way to make it work.

    The best I could come up with today's experiment was the WebGL using the FallBack shader which results in mesh trying to fit inside the batch bounds (like a hot air ballon). The WebPlayer on the other hand showed only skybox.

    I'll probably add some controls to the scene (from first video) so it can be interacted with and make a demo out of it.
     
  6. MikaelTroc

    MikaelTroc

    Joined:
    Nov 2, 2012
    Posts:
    33
    Any idea about the price?
     
  7. Kekec

    Kekec

    Joined:
    Jul 12, 2015
    Posts:
    24
    Hi,

    It has been a busy few days. Before making a demo I decided that I should probably (finally) test it on Mac and Linux as well because as a Windows user I often forget to annoy my friends to test those platforms :rolleyes:.

    To make the long story short, Instance Batcher now works on OpenGL platforms as well.

    You can download the demo here:
    After all of debugging for OpenGL, I was a bit lazy so I just added the car from the Standard assets to the demo so it has some level of interactivity with the sphere instances.

    The price for Instance Batcher will be 60$ and it will be in the Scripting category. I will take a few more days just to think about if there is something else I should add/change/improve before re-submitting it for the review process.
     
  8. Kekec

    Kekec

    Joined:
    Jul 12, 2015
    Posts:
    24
    Re-submitted the package for review with unity editor versions 5.1 and 5.2. Hope everything goes smooth this time. :)
     
    Last edited: Nov 16, 2015
  9. Kekec

    Kekec

    Joined:
    Jul 12, 2015
    Posts:
    24
  10. ikemen_blueD

    ikemen_blueD

    Joined:
    Jan 19, 2013
    Posts:
    340
    Totally Shader noob question, will this work for iOS devices, Android devices, which use OpenGLES2? Are you planning to support Shader Model 2.0?
     
  11. Kekec

    Kekec

    Joined:
    Jul 12, 2015
    Posts:
    24
    Sorry, but Shader Model 2.0 is not supported, because the key feature of Instance Batcher is using texture sampling in the vertex shader (Vertex Texture Fetch) which is not possible with the Shader Model 2.0.
     
  12. Kekec

    Kekec

    Joined:
    Jul 12, 2015
    Posts:
    24
    My friend just tested it on an Android device with OpenGL ES 3.1 support and it worked, but I can't say yet if it would work with the OpenGL ES 3.0 as well, because the specification of 3.1 introduced the "Independent vertex and fragment shaders". I will try to find a test subject for the 3.0 and let you know if that works.;)
     
    ikemen_blueD likes this.
  13. Kekec

    Kekec

    Joined:
    Jul 12, 2015
    Posts:
    24
    I've finally found some time to make a unity package that can be used to test the target device for the support of features that are required by Instance Batcher.

    You can download the test package here

    The package contains two scenes. The first scene uses normally modified standard shader, and the other one uses a shader that has commented out the "pragma exclude_renderers gles" so it should build even for the OpenGL ES 2.0 target devices if nothing else prevents it.

    After building one of the scenes (try building both only if normal one fails) and if the "game" runs on the device, you should see one of three cases:
    • Red X mark and some text informing you that the target device does not support RGBAFloat texture format.
    • Gray checkmark which means that device supports RGBAFloat texture format, but it doesn't support Vertex Texture Fetch (sampling texture inside vertex shader).
    • Green checkmark which means RGBAFloat texture format and the Vertex Texture Fetch is supported by the target device.
    In short: if you get a green checkmark, then that target device should be able to run Instance Batcher.

    InstanceBatcher_FeaturesSupportTestResults.png

    The package was made with Unity 5.2 (if you require the 5.1 version, let me know).

    Feedback on whether or not the test worked on your target device is welcomed :)


    On a side note, let me just say that if you intend to use Instance Batcher on a mobile device, consider how many objects would use it and what the size of batches would be. I'm just saying this because I know mobile devices don't have the luxury of large memory, and the Instance Batcher creates batched meshes which are about the size of original mesh size multiplied by the size of a batch (maximum number of instances in a single batch).
     
  14. GCatz

    GCatz

    Joined:
    Jul 31, 2012
    Posts:
    281
    can there be a fallback for OpenGL ES 2.0 so the batching process will be deactivated,
    and use just the standard shader instead ?
     
  15. Kekec

    Kekec

    Joined:
    Jul 12, 2015
    Posts:
    24
    The batching process is not a matter of a shader, because the batching happens in the edit time. During the runtime shader only makes sure to re-position part of the mesh to where the instance should be, and to hide the rest of mesh of that batch that is not being used.

    The main purpose of Instance Batcher is to avoid the runtime overhead that comes from transforming each vertex in a mesh on the CPU before it can be batched, which is what Dynamic batching already does.
    That is why Instance Batcher works in such a way that it prepares the mesh containing multiple instances. For example if you have a base mesh that has 655 vertices, Instance Batcher can make a batched mesh containing up to 100 instances. This however does not limit you to using exactly 100 instances. During the runtime you can freely spawn and destroy instances and the Instance Batcher will only create a new batch once you exceed those 100 instances (or 200, 300, ...). You can even create several batches and the Instance Batcher will swap to larger one if it cannot fit all instances into current batch size. It will also swap to smaller batch size if it can (swap to smaller batch currently only occurs if instances count is at 75% of the smaller batch size).
     
  16. Kekec

    Kekec

    Joined:
    Jul 12, 2015
    Posts:
    24
  17. Kekec

    Kekec

    Joined:
    Jul 12, 2015
    Posts:
    24
    Just noticed Instance Batcher got into Staff Pick list, so I thought this deserves a screenshot :p

    InstanceBatcherStaffPickPage.png
     
    theANMATOR2b likes this.
  18. Eriks-indesign

    Eriks-indesign

    Joined:
    Aug 15, 2012
    Posts:
    50
    What do you mean by "Does not work with light probes and/or reflection probes.". I don't understand how this doesn't render this tool useless? I was considering buying this tool for our team where we only have custom shaders and some larger complex dynamic meshes, but all of them are reliant on light probes and reflection probes. Can you explain further on this? :)
     
  19. Kekec

    Kekec

    Joined:
    Jul 12, 2015
    Posts:
    24
    Hi, sorry for late reply.

    Well not all visual styles require reflections or light probes :). You can have nice graphics using diffuse shaders and dynamic lights. If your materials are reliant on light / reflection probes, then Instance Batcher in its current state is not a good choice for you, like you said.

    On the technical side of why I haven't implemented the light/reflection probes back then is the fact that the material was filled with the probe that was closest to the mesh origin. Which in case of Instance Batcher's mesh it is the center of the bounding box surrounding the batched instances. And if you have multiple probes you would quickly noticed that something is "off". Same reason as why Unity's Dynamic Batching does not work on objects that use light or reflection probes. So you need to look at Instance Batcher more like dynamic batching with increased number of vertices (of base mesh).

    I admit I was planning to look into adding support for light/reflection probes, but as it happened Unity started making regular changes to their Standard Material shader starting with Unity version 5.2 and I was planning to do more work on Instance Batcher when Unity 5.3 would be released.
    But Unity 5.3 release was heavily delayed and did not even have fully implemented instancing support in the shaders, which meant that if I would rework the standard material back then, I would probably have to go through the same procedure again when they would finally implement it. And going through all of the unity's standard material shader code just to modify it into Instance Batcher's variation is a bit time consuming.
    As it stands now, I don't have the time to rewrite the asset for newer version of unity. And because Unity now offers instancing support I think it is probably a better option if you are developing for PC. For a mobile devices (with opengl es 3.1 support) my approach is still ok as long as you take into account of how much memory it can consume.

    Hope this clears up a few things :)
     
  20. Kusras

    Kusras

    Joined:
    Jul 9, 2015
    Posts:
    134
    Hi I am wondering why this thread is so short for something being 2 years out. I see on screens that with mesh complexicity the effectivness drops. What I am afraid of is, that it is still version 1.0 which was released long time ago and unity changed a lot since then.
     
  21. Kekec

    Kekec

    Joined:
    Jul 12, 2015
    Posts:
    24
    Sorry for late reply.

    Not sure how you are looking at the screenshots of profiler, but lower the graph is the better it is for performance, since it means more frames per second. And mesh complexity has smaller performance hit comparing to large number of smaller meshes that cause dynamic batching overhead or that cannot be batched dynamically and therefore generate a lot of draw calls (which are not good for performance).

    You are right, unity has changed since this asset was released, and I'm considering of removing the asset from the store, since I do not have the time to rework it for latest unity versions. And the reason it remained at version 1.0 is because at the time it was released unity was making numerous changes to standard shader and was adding instancing support which negates the purposes of using this asset almost 100%. And remaking the standard shader variation that works with Instance Batcher is not something that is done in 5 minutes work, since one has to go through all the standard shader changes and make sure everything is working as it should.

    So for now I'm leaving the asset as it is in case someone might still be using old unity version and find it useful.

    PS: the thread is probably short because I knew from day 1 that not many people would find this useful (therefore not many questions).