You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
CrowdControl/Assets/3rd/StompyRobot/SRDebugger/Scripts/Profiler/SRPProfilerService.cs

137 lines
4.0 KiB
C#

1 month ago
#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