SRPProfilerService.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #if UNITY_2018_1_OR_NEWER
  2. namespace SRDebugger.Profiler
  3. {
  4. using System.Collections;
  5. using System.Diagnostics;
  6. using SRDebugger.Services;
  7. using SRF;
  8. using SRF.Service;
  9. using UnityEngine;
  10. #if UNITY_2019_3_OR_NEWER
  11. using UnityEngine.Rendering;
  12. #else
  13. using UnityEngine.Experimental.Rendering;
  14. #endif
  15. public class SRPProfilerService : SRServiceBase<IProfilerService>, IProfilerService
  16. {
  17. public float AverageFrameTime { get; private set; }
  18. public float LastFrameTime { get; private set; }
  19. public CircularBuffer<ProfilerFrame> FrameBuffer
  20. {
  21. get { return _frameBuffer; }
  22. }
  23. private const int FrameBufferSize = 400;
  24. private readonly CircularBuffer<ProfilerFrame> _frameBuffer = new CircularBuffer<ProfilerFrame>(FrameBufferSize);
  25. private ProfilerLateUpdateListener _lateUpdateListener;
  26. // Time between first Update() and last LateUpdate()
  27. private double _updateDuration;
  28. // Time that render pipeline starts
  29. private double _renderStartTime;
  30. // Time between scripted render pipeline starts + EndOfFrame
  31. private double _renderDuration;
  32. private readonly Stopwatch _stopwatch = new Stopwatch();
  33. protected override void Awake()
  34. {
  35. base.Awake();
  36. _lateUpdateListener = gameObject.AddComponent<ProfilerLateUpdateListener>();
  37. _lateUpdateListener.OnLateUpdate = OnLateUpdate;
  38. CachedGameObject.hideFlags = HideFlags.NotEditable;
  39. CachedTransform.SetParent(Hierarchy.Get("SRDebugger"), true);
  40. #if UNITY_2019_3_OR_NEWER
  41. RenderPipelineManager.beginFrameRendering += RenderPipelineOnBeginFrameRendering;
  42. #else
  43. RenderPipeline.beginFrameRendering += RenderPipelineOnBeginFrameRendering;
  44. #endif
  45. StartCoroutine(EndOfFrameCoroutine());
  46. }
  47. protected override void Update()
  48. {
  49. base.Update();
  50. EndFrame();
  51. // Set the frame time for the last frame
  52. if (FrameBuffer.Count > 0)
  53. {
  54. var frame = FrameBuffer.Back();
  55. frame.FrameTime = Time.unscaledDeltaTime;
  56. FrameBuffer[FrameBuffer.Count - 1] = frame;
  57. }
  58. LastFrameTime = Time.unscaledDeltaTime;
  59. var frameCount = Mathf.Min(20, FrameBuffer.Count);
  60. var f = 0d;
  61. for (var i = 0; i < frameCount; i++)
  62. {
  63. f += FrameBuffer[FrameBuffer.Count - 1 - i].FrameTime;
  64. }
  65. AverageFrameTime = (float)f / frameCount;
  66. _stopwatch.Start();
  67. }
  68. IEnumerator EndOfFrameCoroutine()
  69. {
  70. var endOfFrame = new WaitForEndOfFrame();
  71. while (true)
  72. {
  73. yield return endOfFrame;
  74. _renderDuration = _stopwatch.Elapsed.TotalSeconds - _renderStartTime;
  75. }
  76. }
  77. protected void PushFrame(double totalTime, double updateTime, double renderTime)
  78. {
  79. _frameBuffer.PushBack(new ProfilerFrame
  80. {
  81. OtherTime = totalTime - updateTime - renderTime,
  82. UpdateTime = updateTime,
  83. RenderTime = renderTime
  84. });
  85. }
  86. private void OnLateUpdate()
  87. {
  88. _updateDuration = _stopwatch.Elapsed.TotalSeconds;
  89. }
  90. #if UNITY_2019_3_OR_NEWER
  91. private void RenderPipelineOnBeginFrameRendering(ScriptableRenderContext context, Camera[] cameras)
  92. #else
  93. private void RenderPipelineOnBeginFrameRendering(Camera[] obj)
  94. #endif
  95. {
  96. _renderStartTime = _stopwatch.Elapsed.TotalSeconds;
  97. }
  98. private void EndFrame()
  99. {
  100. if (_stopwatch.IsRunning)
  101. {
  102. PushFrame(_stopwatch.Elapsed.TotalSeconds, _updateDuration, _renderDuration);
  103. _stopwatch.Reset();
  104. _stopwatch.Start();
  105. }
  106. _updateDuration = _renderDuration = 0;
  107. }
  108. }
  109. }
  110. #endif