Search Unity

Question Drawing a list of meshes(not same) at once API?

Discussion in 'General Graphics' started by kaiyum, Jul 18, 2022.

  1. kaiyum

    kaiyum

    Joined:
    Nov 25, 2012
    Posts:
    686
    There are API method in graphics class that lets us to draw same mesh N times. How about different meshes that shares same material? Or same material with different instanced properties? Is there anything like it?
     
  2. INedelcu

    INedelcu

    Unity Technologies

    Joined:
    Jul 14, 2015
    Posts:
    173
    For same material with different instanced properties check Graphics.RenderMeshInstanced and pass instance properties in RenderParams.matProps (first argument of RenderMeshInstanced).
     
    kaiyum likes this.
  3. kaiyum

    kaiyum

    Joined:
    Nov 25, 2012
    Posts:
    686
    Great. But about
    Code (CSharp):
    1. Graphics.RenderMeshes(Mesh[] meshes, Material mat, NativeArray<T> instanceData);
    Is there any functionality to draw multiple unique meshes with a single draw call?
     
  4. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    5,060
    Yes, use the line of code you just pasted.
    They just need the same material
     
  5. c0d3_m0nk3y

    c0d3_m0nk3y

    Joined:
    Oct 21, 2021
    Posts:
    672
    @DevDunk, you misunderstood what kaiyum was asking. There is no RenderMeshes method.

    I think, the only way to do this is to merge the meshes first. After all, you can have only one vertex buffer and index buffer bind call if you want to render it all with one draw.

    See Mesh.CombineMeshes
     
    kaiyum likes this.
  6. kaiyum

    kaiyum

    Joined:
    Nov 25, 2012
    Posts:
    686
    Thank you, yes I wanted to render many meshes rather than one mesh. Combining meshes is not handy. What if the meshes are dynamic and changes position every frame, yet have same material?
    In such cases, something like "RenderMeshes" would be helpful. At this stage of unity, what I think of, is completely taking over control of rendering with native rendering plugin and passing ECS like data around through interop.

    At first I thought there is something in unity for this already. Alas, there isn't!
     
  7. c0d3_m0nk3y

    c0d3_m0nk3y

    Joined:
    Oct 21, 2021
    Posts:
    672
    It's an interesting question. I googled a bit and found this:

    What you are trying to do is called MultiDrawIndirect. There is an extension for OpenGl called GL_ARB_multi_draw_indirect. There is also a DX12 method called ExecuteIndirect and a Vulkan method called
    vkCmdDraw[Indexed]Indirect.

    For DX11, there is only a NVAPI extension by NVidia: https://docs.google.com/spreadsheets/d/1J_HIRVlYK8iI4u6AJrCeb66L5W36UDkd9ExSCku9s_o/edit#gid=0

    So technically, it's possible with the latest APIs.
     
    kaiyum likes this.
  8. c0d3_m0nk3y

    c0d3_m0nk3y

    Joined:
    Oct 21, 2021
    Posts:
    672
    richardkettlewell, DevDunk and kaiyum like this.
  9. kaiyum

    kaiyum

    Joined:
    Nov 25, 2012
    Posts:
    686
    I wanted to support very old android devices. The idea was to render meshes of same material in a single go. Since the latest API is most likely not be supported by old devices, so it seems like "nothing can be done about it".
    For static meshes, I have used runtime static batching with combine utility(not that one but the other one).

    Edit: My meshes are quite large. 1k-1.5k each and about 40-60 meshes.
     
  10. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,285
    There isn't anything I know of to do what you want on those devices. I guess you are trying to optimize by reducing the draw call count, but this isn't a way to do that. If the meshes are different they must be submitted as different draw calls. Binding the mesh geometry is part of what makes a draw call. It must be done once for each unique mesh, at the device layer, until you get into the world of more modern techniques such as the multi-draw indirect API mentioned, which requires modern hardware.

    Dynamic batching is an optimization where, on some old devices, such as android/GLES 2, it can be faster to merge a few small meshes into one, and submit one draw call. But the limit for us taking that path is a few hundred vertices, because after that, the cost of copying data into 1 shared buffer outweighs any potential benefit of saving the draw calls. And it's very "iffy" in a lot of cases whether dynamic batching is ever a good idea. We don't advise using it on new hardware, and I believe it is disabled by default on certain project types (eg HDRP) because it is almost obsolete as an effective optimization technique.
     
    kaiyum likes this.
  11. joelv

    joelv

    Unity Technologies

    Joined:
    Mar 20, 2015
    Posts:
    203
    We have introduced (or more like rewritten) an API in 2022.1 which allows you to much more efficiently draw many meshes. See this forum post for more information https://forum.unity.com/threads/new-batchrenderergroup-api-for-2022-1.1230669/

    It's not perfect. You will still get a separate draw call for each mesh of course, but you can skip a lot of layers in the unity engine. The downside is of course that you will be responsible for setting up a lot of things yourself.

    We are hoping to land something like MDI for this interface in the future.