129 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C#
		
	
	
	
		
		
			
		
	
	
			129 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C#
		
	
	
	
|  | namespace SRDebugger.Profiler | |||
|  | { | |||
|  |     using System.Diagnostics; | |||
|  |     using Services; | |||
|  |     using SRF; | |||
|  |     using SRF.Service; | |||
|  |     using UnityEngine; | |||
|  | 
 | |||
|  |     public class ProfilerServiceImpl : SRServiceBase<IProfilerService>, IProfilerService | |||
|  |     { | |||
|  |         public float AverageFrameTime { get; private set; } | |||
|  |         public float LastFrameTime { get; private set; } | |||
|  | 
 | |||
|  |         public CircularBuffer<ProfilerFrame> FrameBuffer | |||
|  |         { | |||
|  |             get { return _frameBuffer; } | |||
|  |         } | |||
|  | 
 | |||
|  |         private const int FrameBufferSize = 400; | |||
|  | 
 | |||
|  |         private readonly CircularBuffer<ProfilerFrame> | |||
|  |             _frameBuffer = new CircularBuffer<ProfilerFrame>(FrameBufferSize); | |||
|  | 
 | |||
|  |         private ProfilerLateUpdateListener _lateUpdateListener; | |||
|  | 
 | |||
|  |         private readonly Stopwatch _stopwatch = new Stopwatch(); | |||
|  | 
 | |||
|  |         // Time between first Update() and last LateUpdate(). | |||
|  |         private double _updateDuration; | |||
|  | 
 | |||
|  |         // Time that first camera rendered. | |||
|  |         private double _renderStartTime; | |||
|  | 
 | |||
|  |         // Time between first camera prerender and last camera postrender. | |||
|  |         private double _renderDuration; | |||
|  | 
 | |||
|  |         private int _camerasThisFrame; | |||
|  | 
 | |||
|  |         protected override void Awake() | |||
|  |         { | |||
|  |             base.Awake(); | |||
|  |             _lateUpdateListener = gameObject.AddComponent<ProfilerLateUpdateListener>(); | |||
|  |             _lateUpdateListener.OnLateUpdate = OnLateUpdate; | |||
|  | 
 | |||
|  |             CachedGameObject.hideFlags = HideFlags.NotEditable; | |||
|  |             CachedTransform.SetParent(Hierarchy.Get("SRDebugger"), true); | |||
|  | 
 | |||
|  |             Camera.onPreRender += OnCameraPreRender; | |||
|  |             Camera.onPostRender += OnCameraPostRender; | |||
|  |         } | |||
|  | 
 | |||
|  |         protected override void Update() | |||
|  |         { | |||
|  |             base.Update(); | |||
|  | 
 | |||
|  |             _camerasThisFrame = 0; | |||
|  | 
 | |||
|  |             EndFrame(); | |||
|  | 
 | |||
|  |             // Set the frame time for the last frame | |||
|  |             if (FrameBuffer.Count > 0) | |||
|  |             { | |||
|  |                 var frame = FrameBuffer.Back(); | |||
|  |                 frame.FrameTime = Time.unscaledDeltaTime; | |||
|  |                 FrameBuffer[FrameBuffer.Count - 1] = frame; | |||
|  |             } | |||
|  | 
 | |||
|  |             LastFrameTime = Time.unscaledDeltaTime; | |||
|  | 
 | |||
|  |             var frameCount = Mathf.Min(20, FrameBuffer.Count); | |||
|  | 
 | |||
|  |             var f = 0d; | |||
|  |             for (var i = 0; i < frameCount; i++) | |||
|  |             { | |||
|  |                 f += FrameBuffer[FrameBuffer.Count - 1 - i].FrameTime; | |||
|  |             } | |||
|  | 
 | |||
|  |             AverageFrameTime = (float) f / frameCount; | |||
|  | 
 | |||
|  |             _stopwatch.Start(); | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void PushFrame(double totalTime, double updateTime, double renderTime) | |||
|  |         { | |||
|  |             //UnityEngine.Debug.Log("Frame: u: {0} r: {1}".Fmt(updateTime, renderTime)); | |||
|  | 
 | |||
|  |             _frameBuffer.PushBack(new ProfilerFrame | |||
|  |             { | |||
|  |                 OtherTime = totalTime - updateTime - renderTime, | |||
|  |                 UpdateTime = updateTime, | |||
|  |                 RenderTime = renderTime | |||
|  |             }); | |||
|  |         } | |||
|  | 
 | |||
|  |         private void OnLateUpdate() | |||
|  |         { | |||
|  |             _updateDuration = _stopwatch.Elapsed.TotalSeconds; | |||
|  |         } | |||
|  | 
 | |||
|  |         private void OnCameraPreRender(Camera cam) | |||
|  |         { | |||
|  |             if (_camerasThisFrame == 0) | |||
|  |             { | |||
|  |                 _renderStartTime = _stopwatch.Elapsed.TotalSeconds; | |||
|  |             } | |||
|  | 
 | |||
|  |             _camerasThisFrame++; | |||
|  |         } | |||
|  | 
 | |||
|  |         private void OnCameraPostRender(Camera cam) | |||
|  |         { | |||
|  |             _renderDuration = _stopwatch.Elapsed.TotalSeconds - _renderStartTime; | |||
|  |         } | |||
|  | 
 | |||
|  |         private void EndFrame() | |||
|  |         { | |||
|  |             if (_stopwatch.IsRunning) | |||
|  |             { | |||
|  |                 PushFrame(_stopwatch.Elapsed.TotalSeconds, _updateDuration, _renderDuration); | |||
|  | 
 | |||
|  |                 _stopwatch.Reset(); | |||
|  |                 _stopwatch.Start(); | |||
|  |             } | |||
|  | 
 | |||
|  |             _updateDuration = _renderDuration = 0; | |||
|  |         } | |||
|  |     } | |||
|  | } |