Search Unity

Graphics.DrawMesh/DrawMeshInstanced fundamentally bottlenecked by the CPU

Discussion in 'General Graphics' started by jbooth, Sep 2, 2016.

  1. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    27,968
    This is why you use DrawMeshInstanced and DrawMeshInstancedIndirect. These two are less, and not at at all bottlenecked respectively.
     
  2. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    872
    But as far as i see these are only available where instancing is available
     
    hippocoder likes this.
  3. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    27,968
    I see, sorry didn't realise thread was this old, was just doing my rounds of leaving tips on threads, I do it once a day or so to orient people that might be lost. Erm.. yeah :/ sorry.
     
    Flavelius likes this.
  4. projectorgames_unity

    projectorgames_unity

    Joined:
    Oct 15, 2018
    Posts:
    49
    So.. what happened with this. This is the only google result for "DrawMeshPersistent" . I want to draw a lot of meshes that don't move, and they're all unique, so this would be ideal for performance.
     
    deus0 likes this.
  5. LennartJohansen

    LennartJohansen

    Joined:
    Dec 1, 2014
    Posts:
    2,388
    Use drawMeshInstancedIndirect. All instances on the GPU already and a superfast drawcall to submit.
     
  6. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,063
    We ended up modifying our version of Unity to have this for the project (source access), as this was needed for older phones that don't support instancing. However, given the market shade of openGLES 2.0 phones, at this point they aren't really worth supporting and using instancing is the viable option.
     
    hippocoder likes this.
  7. Dinamytes

    Dinamytes

    Joined:
    Nov 3, 2016
    Posts:
    50
    But you have to do the culling yourself, camera frustum culling is easy, but shadow casters i can't find out :(
     
  8. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    5,278
    that
     
  9. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    9,952
    I am interested too in self shadowing and shadow casting from instamced indirect in urp, is there any sample or tutorial on this ?
     
  10. Arycama

    Arycama

    Joined:
    May 25, 2014
    Posts:
    174
    In Unity 2019.3 onwards, you can use BatchRendererGroup, in the Built-In Pipeline at least. (Haven't tested in HDRP yet, but there's probably a reasonable chance it will work).
     
    nasos_333 likes this.
  11. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    5,278
    where?
     
  12. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    872
    This doesn't seem to help with rendering, only culling
     
  13. projectorgames_unity

    projectorgames_unity

    Joined:
    Oct 15, 2018
    Posts:
    49
    I mean... I guess? You saw the bit where OP said 'unique' meshes?
     
  14. Arycama

    Arycama

    Joined:
    May 25, 2014
    Posts:
    174
    BatchRenderererGroup lets you essentially create your own Draw Calls which can contain a combination of materials, meshes, submeshes, matrices and anything else you need to render a mesh. It correctly interacts with lighting, shadows, etc.

    The "Culling Callback" is a function that gets called once a frame, which you can use to perform custom culling logic, and control which meshes are drawn, where they appear, (By setting their matrices), etc.

    I've used it to replace a bunch of Graphics.DrawMeshInstanced calls for a Quadtree-Ocean system. The original Graphics.DrawMeshInstanced approach didn't work with multiple lights, but the new approach works nicely. It also works in scene and game view automatically with nothing but an [ExecuteAlways] attribute.

    I can't really provide my source code unfortunately, but the basics are pretty simple:
    -Create a new BatchRendererGroup, and assign a function to the culling callback
    -Call AddBatch to the renderer group with your mesh, material, bounds, etc.
    -Put logic in the culling callback to set the matrices of the mesh to control where it is drawn, and do culling. You'll have to google a bit to figure this out but there's some tutorials (In other languages, but they're understandable enough with google translate) to do this.

    https://docs.unity3d.com/ScriptReference/Rendering.BatchRendererGroup.AddBatch.html
     
  15. Arycama

    Arycama

    Joined:
    May 25, 2014
    Posts:
    174
    So I thought BatchRendererGroup was the solution to all of the problems of Graphics.DrawMesh (And similar functions), but apparently it's only designed to work with Hybrid Renderer and as of 2020.2, it will not work with anything that does not use Hybrid Renderer.

    https://issuetracker.unity3d.com/is...ith-urp-materials-when-srp-batcher-is-enabled

    (Hybrid Renderer also seems to be broken in 2020.2)
    https://forum.unity.com/threads/entities-invisible-with-hybrid-renderer-v2.879544/

    @hippocoder any idea if Unity plans to ever address this issue, nearly 5 years after this thread was made?
     
  16. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    27,968
    I had a nose about and it looks like nothing is going to be done and the focus is on DOTS, but if you could submit a new ticket they'd have something to reference and work with. Right now it doesn't look like this is something they are busy on.

    I don't have the same info Unity's teams have, only public facing stuff so I could be totally wrong here... but more tickets mean prizes basically.
     
    awesomedata likes this.
  17. joelv

    joelv

    Unity Technologies

    Joined:
    Mar 20, 2015
    Posts:
    113
    The BatchRendererGroup is supposed to work without hybrid, but currently it is very hard to use correctly.
    You as a user have to manually ask a material with correctly set up shader for its default value and pass them in using GetBatchVector/ScalarArray. This currently also includes built in unity vars that the shader needs.

    We are aware this is lacking in documentation and have an ongoing task to improve it. We will see if we can improve usability as well over time.
     
    ekakiya, deus0, fherbst and 1 other person like this.
  18. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    27,968
    Docs are an immediate quick fix for which many blocked people will be grateful for, thanks!
     
    awesomedata, Arycama and fherbst like this.
  19. deus0

    deus0

    Joined:
    May 12, 2015
    Posts:
    188
    Hi ahh, noticed DrawMesh doesn't use bounds. I was getting weirdness (looks like bounds are defaulted to points in space for the culling)
    So I wanted to ask, do we use DrawMeshInstancedIndirect instead? This is for say thousands of unique meshes each with custom property (set using computebuffers)
    Or we I try to get the new 'BatchRendererGroup' working? Can't wait for a nicer solution with more customization. The Persistent data and minimal draw calls sounds really sweet.
    I thought perhaps the instanced methods in Graphics had some overhead compared to the DrawMesh function as I have unique meshes. Would be good to know what's recommended here.
     
  20. Digika

    Digika

    Joined:
    Jan 7, 2018
    Posts:
    199
    Ah, splendid, another issue from 2016 that Unity never addressed.
     
  21. SebastianAaltonen

    SebastianAaltonen

    Unity Technologies

    Joined:
    Feb 21, 2020
    Posts:
    112
    I would advice against using BatchRendererGroup API. It's a very low level API that requires deep understanding of Unity shader system internals for correct use. More info here: https://docs.unity3d.com/Packages/c...rid@0.11/manual/batch-renderer-group-api.html

    We are planning to heavily refactor the BatchRendererGroup API. Make it more user friendly and documented. This will however break backwards compatibility with the old API version. I would suggest waiting until we have landed this properly supported API version.
     
    awesomedata and deus0 like this.
  22. gilley033

    gilley033

    Joined:
    Jul 10, 2012
    Posts:
    1,000
    What is the best method for drawing in the scene view and making use of instancing? Should DrawMeshInstanced work (it doesn't for me, but I could be doing something wrong)? Is instancing supported in the scene view? Asking for use in an editor tool.
     
    deus0 likes this.
  23. LaireonGames

    LaireonGames

    Joined:
    Nov 16, 2013
    Posts:
    556
    This is insane.

    Subscribing in case a miracle happens and a sensible solution appears to efficiently render many different objects without GO's.

    Edit: Also, things like BatchRendererGroup should have something on the documentation on its intended use. E.G can I use it for Built In?

    Since its in the scripting documentation with no note it suggests it can, however seeing responses on bugs around it from QA they all say it has to be with URP and hybrid enabled which contradicts what is written here....
     
    Last edited: Sep 6, 2021
    awesomedata likes this.
  24. SebastianAaltonen

    SebastianAaltonen

    Unity Technologies

    Joined:
    Feb 21, 2020
    Posts:
    112
    The miracle is indeed happening. The old BatchRendererGroup API will be gone. The preliminary plan is to land the new BatchRendererGroup to 2022.1. It's a highly efficient way of rendering many different mesh instances without GameObjects.

    The documentation will also be fully rewritten as part of the new API refactoring. The old documentation was very bare as the old API was experimental and written originally for DOTS/Megacity. The new API will have full test coverage and full documentation.

    Some additional documentation about the old BatchRendererGroup API can be found in the DOTS hybrid renderer documentation:
    https://docs.unity3d.com/Packages/c...rid@0.11/manual/batch-renderer-group-api.html

    The BatchRendererGroup API is built on top of the SRP Batcher. It requires a Scriptable Render Pipeline, such as HDRP or URP. Built-in render pipeline is not supported.
     
  25. LaireonGames

    LaireonGames

    Joined:
    Nov 16, 2013
    Posts:
    556
    As usual this all sounds well and good, but the real miracle will be Unity delivering on their promises
     
    cecarlsen likes this.
  26. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    913
    You know, we wouldn't have to muck around with manually rendering stuff if Unity didn't use so darn much main thread time for drawing Renderers. I'm working on a project that uses a couple thousands SpriteRenderers and Unity spends over a dozen milliseconds in the main thread on rendering tasks on the PS4. Now I have to create my own GPU-based SpriteRenderer replacement to compensate for bad engine code.
     
  27. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    1,338
    Does this include some level of LOD handling and/or HLOD support? -- Or is this just barebones instancing? :(

    The former is critical to efficient level/environment design in open world / streaming games, and so should be scene-independent (for the purposes of lightmaps/culling/volumes/etc. either being processed externally by something like Houdini or Blender) in order to enable artists to quickly generate and render meshes without tying them directly to scenes (possibly like the USD format).

    Currently lightmapping and other editing for 64-bit transforms and/or streaming mesh data (akin to MegaCity -- but while also including floating origin and texture streaming support) is impossible without this level of support. THAT is the sort of more "universal" rendering and instancing support that would be the real miracle here -- and it should be built into the Unity Editor directly by default. :(
     
unityunity