Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Question How to use ProfilingScope correctly?

Discussion in 'General Graphics' started by zhoucy001, Nov 28, 2022.

  1. zhoucy001

    zhoucy001

    Joined:
    Jul 15, 2019
    Posts:
    7
    I'm wondering the usage of
    Code (CSharp):
    1. using (new ProfilingScope(cmd, profilingSampler))
    2. {
    3. // do something
    4. }
    I‘m trying to use this to make FrameDebugger、RenderDoc and Profiler display correct information as the URP sample.
    I follow the tips in https://forum.unity.com/threads/profilingsample-usage-in-custom-srp.638941/,it does work on FrameDebugger and I can get nested samples, but on RenderDoc there is some redundant information(not too bad and I don't care much though). Worsely, when I active Profiler it starts report errors like this:

    Missing Profiler.EndSample (Every BeginSample call must have a subsequent EndSample call within the same frame): DrawOpaquePass
    Previous 5 samples:
    DrawOpaquePass
    DrawOpaquePass
    DepthOnlyPass
    RenderLoop.Draw
    Semaphore.WaitForSignal
    In the scope:
    DrawOpaquePass
    DrawOpaquePass
    Render Thread

    Non-matching Profiler.EndSample (Every EndSample call must have a preceding BeginSample call within the same frame): Camera
    Previous 5 samples:
    Camera
    JobAlloc.Grow
    RenderLoop.CleanupNodeQueue
    DrawSkyBox
    RenderLoop.CleanupNodeQueue
    In the scope:
    Camera
    UnityEngine.CoreModule.dll!UnityEngine.Rendering::RenderPipelineManager.DoRenderLoop_Internal() [Invoke]
    PlayerLoop
    Main Thread

    Maybe there are more rules for the usage of ProfilingScope and I have difficulty to sum them up.
    More questions:
    1) Should the name of cmd match the name of profilingSampler?
    URP source code say:
    Code (CSharp):
    1. // Caution: Name of sampler MUST not match name provide to cmd.BeginSample(), otherwise
    2. // we get a mismatch of marker when enabling the profiler.
    When I debug the URP C# code I also find sometimes the name of cmd is empty string.But when I try it on my own Project, if the names not match,FrameDebugger and RenderDoc show wrong sample information.
    2) I also find URP C# code like this:
    Code (CSharp):
    1. using (new ProfilingScope(null, m_ProfilingSampler))
    2. {
    3. // do something
    4. }
    The NULL commandbuffer really confuse me,why it is NULL, and when should I set the cmd NULL?
     
  2. zhoucy001

    zhoucy001

    Joined:
    Jul 15, 2019
    Posts:
    7
    The problem of Profiler Window error is solved, just follow the Caution of URP code:
    Name of sampler MUST NOT match name provide to cmd.BeginSample()
    But the null command buffer still confuse me.
     
  3. c0d3_m0nk3y

    c0d3_m0nk3y

    Joined:
    Oct 21, 2021
    Posts:
    256
    I've never used this class but I took a quick look at the source:
    https://github.com/Unity-Technologi...ines.core/Runtime/Debugging/ProfilingScope.cs

    Source code contains the following comment regarding named command buffers:
    Code (CSharp):
    1.             // NOTE: Do not mix with named CommandBuffers.
    2.             // Currently there's an issue which results in mismatched markers.
    3.             // The named CommandBuffer will close its "profiling scope" on execution.
    4.             // That will orphan ProfilingScope markers as the named CommandBuffer marker
    5.             // is their "parent".
    6.             // Resulting in following pattern:
    7.             // exec(cmd.start, scope.start, cmd.end) and exec(cmd.start, scope.end, cmd.end)
    And regarding the null command buffers. I only took a glimpse but I'm pretty sure it means that you won't get GPU timings in that case. It will skip the cmd.BeginSample call if you don't pass a command buffer. So most likely everything with "gpu" in it will return zero then. So pass null if you only want to measure the CPU time.

    Code (CSharp):
    1.         /// <summary>
    2.         /// GPU Elapsed time in milliseconds.
    3.         /// </summary>
    4.         public float gpuElapsedTime => m_Recorder.enabled ? m_Recorder.gpuElapsedNanoseconds / 1000000.0f : 0.0f;
    5.         /// <summary>
    6.         /// Number of times the Profiling Sampler has hit on the GPU
    7.         /// </summary>
    8.         public int gpuSampleCount => m_Recorder.enabled ? m_Recorder.gpuSampleBlockCount : 0;
    9.         /// <summary>
    10.         /// CPU Elapsed time in milliseconds (Command Buffer execution).
    11.         /// </summary>
    12.         public float cpuElapsedTime => m_Recorder.enabled ? m_Recorder.elapsedNanoseconds / 1000000.0f : 0.0f;
    13.         /// <summary>
    14.         /// Number of times the Profiling Sampler has hit on the CPU in the command buffer.
    15.         /// </summary>
    16.         public int cpuSampleCount => m_Recorder.enabled ? m_Recorder.sampleBlockCount : 0;
    17.         /// <summary>
    18.         /// CPU Elapsed time in milliseconds (Direct execution).
    19.         /// </summary>
    20.         public float inlineCpuElapsedTime => m_InlineRecorder.enabled ? m_InlineRecorder.elapsedNanoseconds / 1000000.0f : 0.0f;
    21.         /// <summary>
    22.         /// Number of times the Profiling Sampler has hit on the CPU.
    23.         /// </summary>
    24.         public int inlineCpuSampleCount => m_InlineRecorder.enabled ? m_InlineRecorder.sampleBlockCount : 0;
     
  4. zhoucy001

    zhoucy001

    Joined:
    Jul 15, 2019
    Posts:
    7
    Thanks a lot, it really inspires me!
     
    c0d3_m0nk3y likes this.