Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Make Graphics.drawMeshInstancedIndirect work when game/editor is paused in SRP

Discussion in 'General Graphics' started by I208iN, Feb 15, 2022.

  1. I208iN

    I208iN

    Joined:
    Mar 25, 2017
    Posts:
    3
    Hi,

    This is a post to help people who have had the same problem I've had, with the keywords I've searched for. I've posted this here and not in the SRP forum because that where you search when you don't know this issue is an SRP issue.

    If you are like me, you have Graphics.drawMeshInstancedIndirect in an Update method on a Monobehaviour script and now you would like to make it work when the game is paused, but obviously Update isn't called.

    Old answers like using Camera.onPreCull don't work in SRP (see this thread).

    The solution I've found is to stop calling Graphics.drawMeshInstancedIndirect in an Update function (like shown in the documentation) and create instead a custom render feature for the scriptable render pipeline, thanks to this example in this example project.

    The means I've had to use CommandBuffer.DrawMeshInstancedIndirect instead which doesn't have the same signature and functionalities, so you may have more digging to do. It was fine in my case.

    I'm not sure it's the right way to do this but hopefully it can help you.

    Here is the code for the renderer feature:
    Code (CSharp):
    1. public class GameSpriteRendererFeature : ScriptableRendererFeature
    2. {
    3.     class CustomRenderPass : ScriptableRenderPass
    4.     {
    5.         public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    6.         {
    7.             CommandBuffer commandBuffer = CommandBufferPool.Get("GameSprite");
    8.            
    9.             // eventually calls commandBuffer.DrawMeshInstancedIndirect(...) if the layers match
    10.             ElementRenderer.RenderElements(commandBuffer, renderingData.cameraData.camera.cullingMask);
    11.  
    12.             context.DrawWireOverlay(renderingData.cameraData.camera);
    13.             context.ExecuteCommandBuffer(commandBuffer);
    14.  
    15.             CommandBufferPool.Release(commandBuffer);
    16.         }
    17.     }
    18.  
    19.     CustomRenderPass afterRenderingPrepasses;
    20.  
    21.     public override void Create()
    22.     {
    23.         afterRenderingPrepasses = new CustomRenderPass();
    24.  
    25.         // I don't fully grasp how these work yet, this one works for me for now
    26.         // there is a list in the docs, you may also need several
    27.         afterRenderingPrepasses.renderPassEvent = RenderPassEvent.AfterRenderingPrePasses;
    28.     }
    29.  
    30.     public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    31.     {
    32.         renderer.EnqueuePass(afterRenderingPrepasses);
    33.     }
    34. }
    Finally you have to add this feature to your Universal Renderer Data scriptable object (the one created by default in Assets/Settings/UniversalRenderer.asset). I don't know how HDRP works but hopefully it's the same.
     
    NightElfik likes this.