Search Unity

Hybrid Renderer with unique mesh for each entity

Discussion in 'Data Oriented Technology Stack' started by JakHussain, Sep 30, 2019.

  1. JakHussain

    JakHussain

    Joined:
    Oct 20, 2016
    Posts:
    105
    I'm streaming in geometry from the cloud and each instance of each mesh will almost always be unique. There is also data associated to each one of these meshes such that every instance can fit the same "archetype". I figured using DOTS for this project would be great since I will need maximum performance to handle varying volumes of data coming in but it seems to me that the hybrid renderer is designed to render a single mesh and instance it across each entity that uses it.

    Does DOTS in its current state support unique meshes for each entity and if not, would the stable release in unity 2020.1 support this use case?
     
    Recart likes this.
  2. Recart

    Recart

    Joined:
    Jun 4, 2017
    Posts:
    9
    We have completely different case. We make AAA racing on mobile, and almost all meshes are unique.

    For static geometry all meshes are unique, we have prebaked light in mesh colors, and we bake meshes to reduce drawcalls, and yet we have 400 drawcalls even with PVS tech

    For dynamic geometry we have constant buffer instancing(gles2 have no hardware instancing), it means we prebake all non unique meshes in batches with 32 instances, and render them dynamically in 1 drawcall. and we have 100 - 200 drawcalls of unique meshes for dynamic objects.

    And the rest is gui, which we draw with the same constant buffer instancing technique.


    So almost all of our meshes are unique. and any big project laverages baking for reducing drawcalls, and all meshes in big projects are usually unique
     
  3. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    5,748
    You can have different mesh per entity if you like to.
    Probably can be achieved in similar fashion, as creating and modifying mesh at runtime.

    However, since you will work with different meshes, you are loosing performance benefits of rendering instancing.
    Also, since mesh is part of shared RenderMesh component, different mesh is part of different archetype.

    I am not entirely sure, how your game performance will behave, if you decide to have thousands of different meshes o. The scene. Perhaps depending on meshes complexity.
     
    julian-moschuering likes this.
  4. Recart

    Recart

    Joined:
    Jun 4, 2017
    Posts:
    9
    You can't use instancing on DX9 or gles2(which is still big part of the market)

    Before baking we have ~8 000 drawcalls, and after baking its 200 - 400 drawcalls. its a huge city with lots of details, a lot of explosions flying debris and 8 complex cars.

    So no matter what, big projects will always have lots of unique meshes.
    The question is will unity support dots optimizations for it or not.
     
  5. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    350
  6. JakHussain

    JakHussain

    Joined:
    Oct 20, 2016
    Posts:
    105
    Yeah the limitation around the rendermesh component being shared component data is what's blocking me. Is there any instance of a regular non instanced component data for unique meshes in the current version of the hybrid renderer that I can use? I can't seem to find anything in the docs like that.
     
    Recart likes this.
  7. Recart

    Recart

    Joined:
    Jun 4, 2017
    Posts:
    9
    If you're talking about my case, gles2 doesn't support CBUFFERs, so SRP batcher works only starting with gles3.1

    And we aren't talking about drawcalls we're talking about 500 chunks, with 1 entity in each, because if we use unique meshes SharedComponent create it's own chunk for each.
     
  8. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    350
    I'm not.

    It's wasting alot of memory with 16k each but regarding performance it might be just fine. Variable chunk size was something they might offer in the future to get around the memory overhead. I doubt there will be a non SCD renderer soon.

    There are a couple of ways to work around this now depending on:
    * How many renderers might exist at a time?
    * How many are visible on average?
    * Do you do anything with them other than rendering them?

    You might:
    * Create your own little renderer with a ICD having a index or something as your renderer description and uses DrawMesh to render. I would expect this to be slower thought.
    * Create a legacy renderer and attach it to your Entity using CopyTransformToGameObject.
     
  9. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    5,748
    Sorry, I am not aware of any.

    I think these are good questions, in respect to OP.
    I am a bit in doubt, application will need to run thousands, 10s of thousands of different meshes at same time. Correct me if I am wrong. Sure, library may contain even million of different meshes, but I suspect, only certain amount will be rendered at given time.

    Alternatively, are there potential meshes, which may contain common lower level LOD?
    If that feasible, you could gain some of performance. Specially on longer distance drawing.

    Check for example Second Life Game, where players were able to bring own meshes and textures. However, there are plots with limited size. I multiplier social game type. While this is perhaps different what you want to do, maybe will give you some ideas.
     
  10. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    2,403
    For any significant number of unique meshes you are likely to need a combine plus partitioning strategy of some type. That's fairly common for this type of problem but the partitioning strategy is often game specific.

    Fortunately done well it should actually be quite performant. You are already starting with having to load in the new mesh somehow. Off the top of my head the flow would look something like select the partition it goes in. Then rebuild that partition including the new mesh data. You can do all of that in jobs including rebuilding normals and render bounds depending on how far you want to take it. So then you just have copying the new partition mesh to the gpu.

    No reason why you can't render the partitions with the hybrid renderer. But the work here is figuring out what your partitioning should look like.
     
  11. Recart

    Recart

    Joined:
    Jun 4, 2017
    Posts:
    9
    So because it's DOTS and Hybrid Rendering is in package we can add our own Rendering System which uses almost the same logic, but with regular non shared components. I didn't implement it yet, but i think it's quite possible to make this case performant.
     
  12. Nyanpas

    Nyanpas

    Joined:
    Dec 29, 2016
    Posts:
    83
    A trick I use is to "bake" shapekeys on skinned meshes to regular meshes, so that you can get a lot of object variation under one drawcall. Consider the following:


    These skulls are all the same skinned mesh with various shapekeys to allow for variations.

    Here are some variations on the shapes after applying the shapekeys and converting them to regular meshes.

    The skulls share the same material with the (unfinished) character on the left. Note the amount of batches.

    With the skulls enabled, only one batch gets added and they are all under one batch. To take this further I can use colour and UV-offset variations in MaterialPropertyBlocking.
     
    florianhanke likes this.
  13. Recart

    Recart

    Joined:
    Jun 4, 2017
    Posts:
    9
    Using Skinned meshes to draw multiple instances in one drawcall is very bad technique.
    Saving drawcalls is not a goal itself, it allows you to save CPU load, and little of GPU load. If you test it i'm pretty shure you will see it slower than other techniques like dynamic batching, instancing, or avaliable on almost every platform constant buffer instancing.
     
  14. Nyanpas

    Nyanpas

    Joined:
    Dec 29, 2016
    Posts:
    83
    They are no longer skinned meshes, but recular meshes when rendered like that. Look at the stats counter for visible skinned meshes. Only the female character is a skinned mesh.