Search Unity

Question How to get SRP batching performance while using command buffer DrawMesh

Discussion in 'Universal Render Pipeline' started by rhedgeco, Oct 21, 2021.

  1. rhedgeco

    rhedgeco

    Joined:
    Dec 2, 2013
    Posts:
    19
    I am working on a custom render feature for the URP pipeline to render special shadows.
    It works fine, but I am loosing a lot of performance when using cmd.DrawMesh within the render feature.

    Is there some way for me to make these command buffer calls without it also calling SetPass under the hood to emulate some resemblance to the SRP batcher?
    I have also tried using Mesh.CombineMesh, but all performance I hope to gain is lost in the costly combining process.

    Any help would be much appreciated. Thanks.
     
  2. rhedgeco

    rhedgeco

    Joined:
    Dec 2, 2013
    Posts:
    19
  3. rhedgeco

    rhedgeco

    Joined:
    Dec 2, 2013
    Posts:
    19
    sad bump :(
     
  4. Andres19899

    Andres19899

    Unity Technologies

    Joined:
    Nov 22, 2016
    Posts:
    4
    Hi there,

    Sorry to hear the post has gone unanswered.

    Our devs monitor forums but it is hard to keep track of every single forum post.

    I am jumping in here with a bit of information I have collected in URP with rendering shading performance.

    Based on my research URP has two rendering paths Forward and deferred.

    https://docs.unity3d.com/Packages/c...ersal-renderer.html#rendering-path-comparison

    As per this post https://forum.unity.com/threads/urp-limited-number-of-pixel-lights-why.1048142/#post-7413566, it seems differed lighting is ideal with working with fewer lights/shadows since performance is improved. Looks like cmd.DrawMesh relies highly on CPU which might create those performance issues you are seeing.

    In this case, it would be a good idea to either go through deferred lighting and then turn off G-buffer normals off to increase performance:

    https://docs.unity3d.com/Packages/c...manual/rendering/deferred-rendering-path.html

    It might be worth checking if you can instance any of the shadows through GPU instead of CPU to reduce performance costs.

    I hope any of this can help you.
     
  5. rhedgeco

    rhedgeco

    Joined:
    Dec 2, 2013
    Posts:
    19
    Thanks for your help and insight. Also I should mention I am not using the built in shadow renderer. I am making my own.
    Unfortunately I cannot go the route of GPU instancing, because all the meshes use different geometry.

    In the Graphics API there is a command for Graphics.DrawMeshNow. Under the hood it is not calling SetPass again, and it is reusing the shader pass from the previous draw. This is also what the SRP batcher is doing. What I am really looking for is a way to do that with command buffers in a render feature.

    It is clear that command buffers closely mirror the Graphics API as all their methods are almost identical. The only method missing is DrawMeshNow(). Is there a way that I can get around this, and achieve the same effect that the SRP batcher does? Can I manually submit meshes to a SRP batcher loop?
     
  6. rhedgeco

    rhedgeco

    Joined:
    Dec 2, 2013
    Posts:
    19
  7. gyx920820

    gyx920820

    Joined:
    Oct 8, 2015
    Posts:
    35
    I'm also confused about this
     
  8. leozzyzheng2

    leozzyzheng2

    Joined:
    Jul 2, 2021
    Posts:
    63
    I have the same question.
    I'm working on an open world game which will have around 100000+ renderers in view frustum after using LOD and Hiz culling, create gameobject with MeshRenderer is unacceptable for CPU usage, the only way is to DrawMesh by my self, so it is very important to reuse the SRPBatcher for those meshes, is there any way to do it?
     
  9. arnaud-carre

    arnaud-carre

    Unity Technologies

    Joined:
    Jun 23, 2016
    Posts:
    97
    Hi!

    CommandBuffer.DrawMesh is using a generic rendering code path that setup GPU completely (including SetPass) so it's not really fast.
    DrawMeshNow doesn't call SetPass but it runs on the main thread and the mesh won't be added in each rendering pass (like depth prepass, shadow etc). For a custom rendering pass it could be ok but keep in mind it still sets some GPU state ( like uploading obj2world matrix one by one ).

    Did you try Graphics.DrawMesh, with just a mesh, matrix & material as arg? ( keep materialPropertyBlock to NULL ). This should use the SRP Batcher code path.

    And then, for maximum performance when dealing with custom mesh rendering, you could use the recent BatchRendererGroup API. It requires a bit more work to setup but it's pretty fast.


    More info here: https://docs.unity3d.com/2022.1/Documentation/Manual/batch-renderer-group.html
     
    adamgolden likes this.
  10. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,555
    Re the platform compatibility listed on the getting started page.. any chance WebGL is also supported (or will be)?
     
  11. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,555
    If @arnaud-carre or anyone else has further insight/clarification, as I understand it, WebGL does support SRP batching, but it isn't listed as a compatible platform for BatchRendererGroup.

    Related quotes from https://www.khronos.org/assets/uplo...ndan-Duncan---Unity-SRP-Batcher-For-WebGL.pdf
    "Fast WebGL Rendering With SRP Batcher"
    "Automatic for all compatible shaders."
    "Coming soon to Unity 2021.2"

    .. then on January 2022, quote from https://mobile.twitter.com/DannyWebbie_/status/1477325774084476929
    "Unity 2021.2 brings URP SRP batching support to WebGL. Thanks to Jukka Jylänki at Unity for developing an extension to Emscripten to make this happen."

    Will it work in 2022.2 beta (or 2023.x) and the lack of listing in platforms was just an oversight, or it's really not supported because of some other technical challenge beyond SRP batching? Or is BatchRendererGroup for WebGL 2 partially supported (i.e. it will work/won't crash if you do use it, but without much benefit over other methods), or ? Thanks!
     
  12. arnaud-carre

    arnaud-carre

    Unity Technologies

    Joined:
    Jun 23, 2016
    Posts:
    97
    Hi,

    SRP Batcher is supported on WebGL. BRG is built on top of SRP Batcher (mainly reusing the persistent material data in GPU memory) but also introduces a complete new GPU data layout. For instance, BRG requires a new shader variant, fetching data from SSBO.

    With the recent BRG support of OpenGLES3.1, we added some new code to bypass the GLES3.1 SSBO access from vertex stage limitation. From a pure GPU perspective, BRG on GLES3.1 is really close to what BRG would be in WebGL.

    But supporting a platform also involves looking at the CPU performance. BRG and more generally entities.graphics rely on Burst & jobsystem support. We should carefully look at how these systems interoperate before making any decision.

    To sum up, WebGL BRG support is not decided yet but product & engineer teams are actively discussing it.
     
    adamgolden likes this.
  13. leozzyzheng2

    leozzyzheng2

    Joined:
    Jul 2, 2021
    Posts:
    63
    Will BatchRendererGroup be ported back to 2021?
    Will it support OpenGLES on Android in the future?
     
    Last edited: Sep 30, 2022