137 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C#
		
	
	
	
		
		
			
		
	
	
			137 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C#
		
	
	
	
| 
								 | 
							
								#if UNITY_2018_1_OR_NEWER
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								namespace SRDebugger.Profiler
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								    using System.Collections;
							 | 
						|||
| 
								 | 
							
								    using System.Diagnostics;
							 | 
						|||
| 
								 | 
							
								    using SRDebugger.Services;
							 | 
						|||
| 
								 | 
							
								    using SRF;
							 | 
						|||
| 
								 | 
							
								    using SRF.Service;
							 | 
						|||
| 
								 | 
							
								    using UnityEngine;
							 | 
						|||
| 
								 | 
							
								#if UNITY_2019_3_OR_NEWER
							 | 
						|||
| 
								 | 
							
								    using UnityEngine.Rendering;
							 | 
						|||
| 
								 | 
							
								#else
							 | 
						|||
| 
								 | 
							
								    using UnityEngine.Experimental.Rendering;
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    public class SRPProfilerService : 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;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        // Time between first Update() and last LateUpdate()
							 | 
						|||
| 
								 | 
							
								        private double _updateDuration;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        // Time that render pipeline starts
							 | 
						|||
| 
								 | 
							
								        private double _renderStartTime;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        // Time between scripted render pipeline starts + EndOfFrame
							 | 
						|||
| 
								 | 
							
								        private double _renderDuration;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private readonly Stopwatch _stopwatch = new Stopwatch();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        protected override void Awake()
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            base.Awake();
							 | 
						|||
| 
								 | 
							
								            _lateUpdateListener = gameObject.AddComponent<ProfilerLateUpdateListener>();
							 | 
						|||
| 
								 | 
							
								            _lateUpdateListener.OnLateUpdate = OnLateUpdate;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            CachedGameObject.hideFlags = HideFlags.NotEditable;
							 | 
						|||
| 
								 | 
							
								            CachedTransform.SetParent(Hierarchy.Get("SRDebugger"), true);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#if UNITY_2019_3_OR_NEWER
							 | 
						|||
| 
								 | 
							
								            RenderPipelineManager.beginFrameRendering += RenderPipelineOnBeginFrameRendering;
							 | 
						|||
| 
								 | 
							
								#else
							 | 
						|||
| 
								 | 
							
								            RenderPipeline.beginFrameRendering += RenderPipelineOnBeginFrameRendering;
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            StartCoroutine(EndOfFrameCoroutine());
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        protected override void Update()
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            base.Update();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            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();
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        IEnumerator EndOfFrameCoroutine()
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            while (true)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                yield return new WaitForEndOfFrame();
							 | 
						|||
| 
								 | 
							
								                _renderDuration = _stopwatch.Elapsed.TotalSeconds - _renderStartTime;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        protected void PushFrame(double totalTime, double updateTime, double renderTime)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            _frameBuffer.PushBack(new ProfilerFrame
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                OtherTime = totalTime - updateTime - renderTime,
							 | 
						|||
| 
								 | 
							
								                UpdateTime = updateTime,
							 | 
						|||
| 
								 | 
							
								                RenderTime = renderTime
							 | 
						|||
| 
								 | 
							
								            });
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private void OnLateUpdate()
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            _updateDuration = _stopwatch.Elapsed.TotalSeconds;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#if UNITY_2019_3_OR_NEWER
							 | 
						|||
| 
								 | 
							
								        private void RenderPipelineOnBeginFrameRendering(ScriptableRenderContext context, Camera[] cameras)
							 | 
						|||
| 
								 | 
							
								#else
							 | 
						|||
| 
								 | 
							
								        private void RenderPipelineOnBeginFrameRendering(Camera[] obj)
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            _renderStartTime = _stopwatch.Elapsed.TotalSeconds;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private void EndFrame()
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (_stopwatch.IsRunning)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                PushFrame(_stopwatch.Elapsed.TotalSeconds, _updateDuration, _renderDuration);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                _stopwatch.Reset();
							 | 
						|||
| 
								 | 
							
								                _stopwatch.Start();
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            _updateDuration = _renderDuration = 0;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								#endif
							 |